功能实现:
在主窗口点击按钮,调出子窗口,并向子窗口传递参数 ;在子窗口输入数据后再向主窗口传递参数 ,并在主窗口显示输入的数据。
代码实现:
1.载入图形化界面
在MainWinGUI.py和ChildWinGUI.py两个文件中编写主窗口和子窗口,并导入它们,实现功能与逻辑分离。
from PyQt6 import QtWidgets, QtCore, QtGui
from PyQt6.QtWidgets import *
import sys
from MainWinGUI import Ui_MainWindow
from ChildWinGUI import Child_MainWindow
运行后操作的界面如下:
主窗口界面
子窗口
2.主窗口功能实现
主窗口只包含两个区域,显示区与Send 1、Send 2按钮。单击Send 1与Send 2都将调出子窗口,并且将向子窗口传递信息究竟是1调用还是2调用的子窗口。其功能实现如下:
class MainForm(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainForm, self).__init__()
self.setupUi(self) # 函数定义来自MainWinGUI.py
# 这里的ChildForm()是我们创建子窗口类
# 我们将其命名为OurNewWindow
self.OurNewWindow = ChildForm() # 子窗口实例化
# 调用子窗口,并向子窗口传递参数
# 方法 1
self.SendButton_1.clicked.connect(self.CallChildWin)
self.SendButton_2.clicked.connect(self.CallChildWin)
# 方法 2,使用lambda传递自定义参数
self.SendButton_1.clicked.connect(lambda: self.CallChildWin(1))
self.SendButton_2.clicked.connect(lambda: self.CallChildWin(2))
使用信号将按键连接到槽或者回调函数(CallChildWin)
self.SendButton_1.clicked.connect()
在回调函数中 判断需要传递的参数 并实现调用子窗口 。这个步骤可以使用两种方式实现:
方法 1:通过在CallChildWin里使用sender().text()对当前按键的名称进行判断后,对btn_num进行赋值,并将其传回子窗口。
def CallChildWin(self):
#初始化子窗口
self.OurNewWindow.init_Ui()
# 显示子窗口
self.OurNewWindow.show()
# 使用sender()获取当前按键名称判断是 Send 1 还是 Send 2
if self.sender().text() == 'Send 1':
self.OurNewWindow.btn_num = 1
else:
self.OurNewWindow.btn_num = 2
此时的btn_num是在子窗口类中定义的整型变量,因此在给它赋值的时候,需要在前面加上子窗口类的名称(OurNewWindow)。这里就能实现向子窗口传递参数 了。
方法 2: 使用Lambda表达式直接向槽传递额外的参数
def CallChildWin(self, num):
# 初始化子窗口
self.OurNewWindow.init_Ui()
# 显示子窗口
self.OurNewWindow.show()
# 根据传入的实参来赋值btn_num
if num == 1:
self.OurNewWindow.btn_num = 1
else:
self.OurNewWindow.btn_num = 2
同样的,btn_num是在子窗口类中定义的整型变量,因此在给它赋值的时候,需要在前面加上子窗口类的名称(OurNewWindow)。这里就能实现向子窗口传递参数 了。
此时主窗口的按钮功能基本写完 ,还需要一个显示接收的子窗口参数的函数:
def display_params(self, arg1, arg2, arg3, arg4):
# 显示
self.textBrowser.append("The shape is: %s" % arg1)
self.textBrowser.append("Length = : %d" % arg2)
self.textBrowser.append("Width = : %f" % arg3)
self.textBrowser.setText("This is sent from Send %d" % arg4)
需要传入的四个形参分别对应:shape(字符串 str)、Length(整型 int)、Width(浮点型 float)和按键编号(整型 int)。
3.子窗口功能实现
子窗口只有三个输入框和一个按键,class ChildForm的定义如下:
class ChildForm(QMainWindow, Child_MainWindow):
# 定义信号
param_signal = QtCore.pyqtSignal(str, int, float, int) # 分别对应shape Length Width num
def __init__(self):
super(ChildForm, self).__init__()
self.setupChildUi(self) # 函数定义来自ChildWinGUI.py
self.retranslateUi(self) # 函数定义来自ChildWinGUI.py
# 定义按键序号
self.btn_num = 0
# 绑定信号和槽
self.Save_button.clicked.connect(self.save_func)
在最开始定义的信号
param_signal = QtCore.pyqtSignal(str, int, float, int)
可以实现将四个值传回主窗口的。并且定义pyqtSignal时,我们需要手动初始化需要传递的参数类型,括号里的(str, int, float, int)便是对应上节display_params()所需要的形参。
Save_func函数将保存用户手动输入的shape, length, width值与主窗口传递过来的btn_num值,并将这四个值传回主窗口。
def save_func(self):
in_type = self.lineEdit_rec.text() # 读取shape输入
in_length = int(self.lineEdit_l.text()) # 读取length输入
in_width = float(self.lineEdit_w.text()) # 读取witdth输入
in_num = self.btn_num # 读取按键编号
# 发送信号
self.param_signal.emit(in_type, in_length, in_width, in_num)
# 保存后关闭子窗口
self.close()
此时,由子窗口向主窗口发送参数的信号已经通过
self.param_signal.emit(in_type, in_length, in_width, in_num)
实现。发送有了,那么如何接收呢?
这就需要回到主窗口的功能实现函数里来接收这个param_signal。
4.接收信号
这一步就很简单了,接收信号,再想要把这个信号如何处理?放入display_params()函数里进行显示。
只需要在CallChildWin()里面加一句:
# 连接信号
self.OurNewWindow.param_signal.connect(self.display_params)
这样便接收了(in_type,in_length,in_width,in_num)四个实参,并将它们传给了display_params()。
结果显示:
Send 1
弹出子窗口,并输入变量
Send 2
结束语:
在使用Pyqt的调用子窗口时,与Matlab的app designer有略微的区别。当时也被这个问题困了一些时间,现在记录下来以便将来遇到时能够提高效率。