窗口数据传递
在开发程序时,如果这个程序只有一个窗口,则应该关心这个窗口里面的各个控件之间是如何传递数据的;如果这个程序有多个窗口,那么还应该关心不同的窗口之间是如何传递数据的。对于多窗口的情况,一般有两种解决办法,其中一种是主窗口获取子窗口中的控件的属性;另外一种是通过信号与槽机制,一般是子窗口通过发射信号的形式传递数据,主窗口的槽函数获取这些数据。
单一窗口数据传递
对于具有单一窗口的程序来说,一个控件的变化会影响另一个控件的变化,这种变化利用信号与槽机制非常容易解决。
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qtclass WinForm(QWidget):def __init__(self):super(WinForm, self).__init__()self.initUI()def initUI(self):# 先创建滑块和LCD控件lcd = QLCDNumber(self)slider = QSlider(Qt.Horizontal, self)vBox = QVBoxLayout()vBox.addWidget(lcd)vBox.addWidget(slider)self.setLayout(vBox)# valueChanged()是QSlider的一个信号函数,只要slider的值发生改变,它就会发射一个信号# 然后通过Connect连接信号的接收控件,也就是lcdslider.valueChanged.connect(lcd.display)self.setGeometry(300, 300, 350, 150)self.setWindowTitle("信号与槽")if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec_())
运行脚本,滑动滑块可以修改数值
多窗口数据传递:调用属性
在PyQt编程过程中,经常会遇到输入或选择多个参数的问题,把多个参数写到一个窗口中,主窗口会显得很臃肿,所以一般是添加一个按钮,调用对话框,在对话框中进行参数的选择,关闭对话框时将参数值返回给主窗口。
PyQt提供了一些标准的对话框类,用于输入数据、修改数据、更改应用的设置等,常见的有QFileDialog、QInputDialog、QColorDialog、QFontDialog等。
DateDialog.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *class DateDialog(QDialog):def __init__(self, parent=None):super(DateDialog, self).__init__(parent)self.setWindowTitle('DateDialog')# 在布局中添加控件layout = QVBoxLayout(self)self.datetime = QDateTimeEdit(self)self.datetime.setCalendarPopup(True)self.datetime.setDateTime(QDateTime.currentDateTime())layout.addWidget(self.datetime)# 使用两个按钮(OK和Cancel)分别连接accept()和reject()槽函数buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)buttons.accepted.connect(self.accept)buttons.rejected.connect(self.reject)layout.addWidget(buttons)# 从对话框中获取当前日期和时间def dateTime(self):return self.datetime.dateTime()# 使用静态函数创建对话框并返回(date, time, accepted)@staticmethoddef getDateTime(parent=None):dialog = DateDialog(parent)result = dialog.exec_()date = dialog.dateTime()return (date.date(), date.time(), result==QDialog.Accepted)
Main.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from DateDialog import DateDialogclass WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)self.resize(400, 90)self.setWindowTitle('对话框关闭时返回值给主窗口')self.lineEdit = QLineEdit(self)self.button1 = QPushButton("弹出对话框1")self.button1.clicked.connect(self.onButton1Click)self.button2 = QPushButton("弹出对话框2")self.button2.clicked.connect(self.onButton2Click)gridLayout = QGridLayout()gridLayout.addWidget(self.lineEdit)gridLayout.addWidget(self.button1)gridLayout.addWidget(self.button2)self.setLayout(gridLayout)def onButton1Click(self):dialog = DateDialog(self)result = dialog.exec_()date = dialog.dateTime()self.lineEdit.setText(date.date().toString())print("\n日期对话框的返回值")print(f'date={date.date()}')print(f"time={date.time()}")print(f'result={result}')dialog.destroy()def onButton2Click(self):date, time, result = DateDialog.getDateTime()self.lineEdit.setText(date.toString())print('\n日期对话框的返回值')print(f'date={date}')print(f'time={time}')print(f"result={result}")if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec_())
运行脚本
多窗口数据传递:信号与槽
对于多窗口的数据传递,一般是通过子窗口发射信号的,主窗口通过槽函数捕获这个信号,然后获取信号里面的数据。子窗口发射的信号有两种,其中一种是发射PyQt内置id一些信号;另一种是发射自定义的信号。
发射自定义信号的好处是,它的参数类型可以自定义。比如发射一个自定义信号,它的参数类型可以为int、str、dict、list等;如果发射内置信号,则只能是特定的几个参数。
DateDialog.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *class DateDialog(QDialog):Signal_OneParameter = pyqtSignal(str)def __init__(self, parent=None):super(DateDialog, self).__init__(parent)self.setWindowTitle("子窗口:用来发射信号")# 在布局中添加控件layout = QVBoxLayout(self)self.label = QLabel(self)self.label.setText("前者发射内置信号\n后者发射自定义信号")self.datetime_inner = QDateTimeEdit(self)self.datetime_inner.setCalendarPopup(True)self.datetime_inner.setDateTime(QDateTime.currentDateTime())self.datetime_emit = QDateTimeEdit(self)self.datetime_emit.setCalendarPopup(True)self.datetime_emit.setDateTime(QDateTime.currentDateTime())layout.addWidget(self.label)layout.addWidget(self.datetime_inner)layout.addWidget(self.datetime_emit)# 使用两个button(ok和Cancel)分别连接accept()和reject()槽函数buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal,self)buttons.accepted.connect(self.accept)buttons.rejected.connect(self.reject)layout.addWidget(buttons)self.datetime_emit.dateTimeChanged.connect(self.emit_signal)def emit_signal(self):date_str = self.datetime_emit.dateTime().toString()self.Signal_OneParameter.emit(date_str)
test.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from DateDialog import DateDialogclass WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)self.resize(400, 90)self.setWindowTitle('信号与槽传递参数的实例')self.open_btn = QPushButton("获取时间")self.lineEdit_inner = QLineEdit(self)self.lineEdit_emit = QLineEdit(self)self.open_btn.clicked.connect(self.openDialog)self.lineEdit_inner.setText("接收子窗口内置信号的时间")self.lineEdit_emit.setText("接收子窗口自定义信号的时间")grid = QGridLayout()grid.addWidget(self.lineEdit_inner)grid.addWidget(self.lineEdit_emit)grid.addWidget(self.open_btn)self.setLayout(grid)def openDialog(self):dialog = DateDialog(self)print(dialog)"""连接子窗口的内置信号与主窗口的槽函数"""dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot)"""连接子窗口的自定义信号与主窗口的槽函数"""dialog.Signal_OneParameter.connect(self.deal_emit_slot)dialog.show()def deal_inner_slot(self, date):self.lineEdit_inner.setText(date.toString())def deal_emit_slot(self, dateStr):self.lineEdit_emit.setText(dateStr)if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec_())
运行脚本