繁体   English   中英

Pyside6中的全局信号?

[英]Global signaling in Pyside6?

我想在我的主窗口中发出一个信号,并且在我想接收该信号的某个组件深处的某个地方发出信号。 我在这里读过一些可以用通用信号类解决的线程,但是我不能让它工作。

我创建了一个带有测试信号的信号管理器类:

class Manager(QObject):
  test_signal = Signal(str)
  def __init__(self):
    QObject.__init__(self)

在我的主窗口中,我这样做:

class MainWindow(QMainWindow):
  def __init__(self):
    super(MainWindow, self).__init__()
    self.signal_manager = SignalManager.Manager()
  def some_button_clicked(self):
    self.signal_manager.test_signal.emit('test')

在某个组件的深处:

class MyTreeWidget(QTreeWidget):
  def __init__(self, parent=None):
    QTreeWidget.__init__(self, parent)
    self.signal_manager = SignalManager.Manager()
    self.signal_manager.test_signal.connect(self.do_something)
  def do_something(self, param):
    # Do something...

所以当我点击我的按钮并且 some_button_clicked 发出事件 do_something() 应该发生但它不会发生。 想知道这里可能是什么问题?

您的解决方案不起作用,因为您总是在创建管理器的实例。

每当我需要依赖 Qt 程序中的一些“全局”对象时,我通常会创建 QApplication 的子类并为它们创建属性,这显然也适用于“全局信号”。

然后您可以通过访问应用程序instance()发出信号或连接到它们:

class MyApp(QApplication):
    globalSignal = pyqtSignal(str)


class TargetLabel(QLabel):
    def __init__(self):
        super().__init__()
        QApplication.instance().globalSignal.connect(self.setText)


app = MyApp([])
window = QWidget()
layout = QVBoxLayout(window)
lineEdit = QLineEdit()
layout.addWidget(lineEdit)
layout.addWidget(TargetLabel())

lineEdit.textChanged.connect(app.globalSignal)

window.show()
app.exec()

另一种方法是在单独的模块中使用全局 QObject 子类,使用对对应于唯一实例的模块的全局引用(使用global实际上有意义的罕见情况之一)。

一个可能的“hacky”实现是创建一个名为信号管理器的函数,并将其全局引用替换为 QObject 的实例,如下例所示:

globalsignal.py

from PyQt5 import QtCore

def GlobalSignalProxy():
    global GlobalSignalProxy
    if not isinstance(GlobalSignalProxy, QtCore.QObject):
        class GlobalSignalProxy(QtCore.QObject):
            signal = QtCore.pyqtSignal(str)
        # replace the function with the instance
        GlobalSignalProxy = GlobalSignalProxy()
    return GlobalSignalProxy

targetlabel.py

from PyQt5 import QtWidgets
from globalsignal import GlobalSignalProxy

class TargetLabel(QtWidgets.QLabel):
    def __init__(self):
        super().__init__()
        GlobalSignalProxy().signal.connect(self.setText)

main.py

from PyQt5 import QtWidgets
from globalsignal import GlobalSignalProxy
from targetlabel import TargetLabel

app = QtWidgets.QApplication([])
window = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout(window)
lineEdit = QtWidgets.QLineEdit()
layout.addWidget(lineEdit)
lineEdit.textChanged.connect(GlobalSignalProxy().signal)
layout.addWidget(TargetLabel())
window.show()
app.exec()

以上显然也可以通过单例类来实现。

无论如何,我不建议这种做法,因为我相信 QApplication 子类会更好,原因有很多,包括它更适合 OOP 模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM