使用信号和插槽在两个小部件之间发送消息

2024-06-25 22:41:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要让小部件在彼此之间进行通信。

我的中心小部件有两个小部件实例:widget A(实例A()),widget B(实例B()) 当widget A受到事件(例如:mouseRelease)影响时, 我需要widget A调用函数并进行一些计算和处理数据。 然后我需要这个处理过的数据传递给widget B, 当从widget A接收到这个数据时,它将用这个数据调用一个函数,处理它,并用它做更多的事情。

这两个小部件都是来自QWidget的自定义小部件。 我几乎可以肯定我需要使用信号和插槽,但我不知道如何实现函数调用部分。

我在这里反复阅读了Qt的解释: http://qt-project.org/wiki/Signals_and_Slots_in_PySide但是我不知道如何连接两个同时发送和发送处理数据的小部件。

我真的很感谢你的帮助。如果你不能用Python回答C++,那么请解释它,而不是完全禁止。


Tags: 数据实例函数信号部件事件widgetqt
3条回答

更新PyQt5的@user1006989答案:

from PyQt5 import QtCore, QtGui, QtWidgets


class widgetB(QtWidgets.QWidget):

    procDone = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetB, self).__init__(parent)

        self.lineEdit = QtWidgets.QLineEdit(self)
        self.button = QtWidgets.QPushButton("Send Message to A", self)
        self.layout = QtWidgets.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

        self.button.clicked.connect(self.on_button_clicked)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procDone.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_procStart(self, message):
        self.lineEdit.setText("From A: " + message)

        self.raise_()


class widgetA(QtWidgets.QWidget):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetA, self).__init__(parent)

        self.lineEdit = QtWidgets.QLineEdit(self)
        self.lineEdit.setText("Hello!")

        self.button = QtWidgets.QPushButton("Send Message to B", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.layout = QtWidgets.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procStart.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_widgetB_procDone(self, message):
        self.lineEdit.setText("From B: " + message)

        self.raise_()


class mainwindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(mainwindow, self).__init__(parent)

        self.button = QtWidgets.QPushButton("Click Me", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.setCentralWidget(self.button)

        self.widgetA = widgetA()
        self.widgetB = widgetB()

        self.widgetA.procStart.connect(self.widgetB.on_procStart)
        self.widgetB.procDone.connect(self.widgetA.on_widgetB_procDone)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.widgetA.show()
        self.widgetB.show()

        self.widgetA.raise_()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    main = mainwindow()
    main.show()
    sys.exit(app.exec_())

下面是一个示例,演示PyQt4中两个小部件之间的信号/插槽连接:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from PyQt4 import QtCore, QtGui

class widgetB(QtGui.QWidget):
    procDone = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetB, self).__init__(parent)

        self.lineEdit = QtGui.QLineEdit(self)
        self.button = QtGui.QPushButton("Send Message to A", self)
        self.layout = QtGui.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

        self.button.clicked.connect(self.on_button_clicked)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procDone.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_procStart(self, message):
        self.lineEdit.setText("From A: " + message)

        self.raise_()

class widgetA(QtGui.QWidget):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetA, self).__init__(parent)

        self.lineEdit = QtGui.QLineEdit(self)
        self.lineEdit.setText("Hello!")

        self.button = QtGui.QPushButton("Send Message to B", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.layout = QtGui.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procStart.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_widgetB_procDone(self, message):
        self.lineEdit.setText("From B: " + message)

        self.raise_()


class mainwindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(mainwindow, self).__init__(parent)

        self.button = QtGui.QPushButton("Click Me", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.setCentralWidget(self.button)

        self.widgetA = widgetA()
        self.widgetB = widgetB()

        self.widgetA.procStart.connect(self.widgetB.on_procStart)
        self.widgetB.procDone.connect(self.widgetA.on_widgetB_procDone)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.widgetA.show()
        self.widgetB.show()

        self.widgetA.raise_()


if __name__ == "__main__":
    import sys

    app  = QtGui.QApplication(sys.argv)
    main = mainwindow()
    main.show()
    sys.exit(app.exec_())

我认为这里可以使用两种不同的方法:使AB类紧密耦合,或者使用主窗口作为中介。

在第一种情况下,您必须“让A知道B”,这意味着A引用了B。在这种情况下,您甚至根本不需要执行signals&slot操作,只需直接调用B的方法即可。

另一种方法是让A发出一个带有参数的信号,该参数包含B应接收的数据,主窗口捕获该信号并用该数据调用B。 或者,您可以将数据放在A的属性中,让主窗口直接从这里获取数据,而不将其作为信号参数传递。

后一种方法允许您更自由地编写AB,因为A不需要知道如何调用B

在代码中解释如下:

class A(QWidget):
    the_signal = Signal(...)
    def mouseReleaseEvent(self, event):
        self.a_function()
        self.the_data = self.produce_data()
        self.the_signal.emit()

class B(QWidget):
    def process_data(self, data):
        pass

class MainWindow(QMainWindow):
    def __init__(self):
        self.a_widget = A()
        self.b_widget = B()
        self.a_widget.the_signal.connect(self.do_process)
        # if the signal has the data as argument:
        # self.a_widget.the_signal.connect(self.b_widget.process_data)
    def do_process(self):
        self.b_widget.process_data(self.a_widget.the_data)

相关问题 更多 >