简体   繁体   English

Pyside6中的全局信号?

[英]Global signaling in Pyside6?

I would like to emit a signal in my main window and somewhere deep down in one of my components I would like to receive that signal.我想在我的主窗口中发出一个信号,并且在我想接收该信号的某个组件深处的某个地方发出信号。 I have read in some thread here that can be solved with a common signal class, however I cannot make it work.我在这里读过一些可以用通用信号类解决的线程,但是我不能让它工作。

I created a signal Manager class with a test signal in it:我创建了一个带有测试信号的信号管理器类:

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

In my main window I do this:在我的主窗口中,我这样做:

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')

Somewhere deep in one of the components:在某个组件的深处:

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...

So when I click my button and some_button_clicked emits the event do_something() should happen but it won't.所以当我点击我的按钮并且 some_button_clicked 发出事件 do_something() 应该发生但它不会发生。 Wondering what could be the problem here?想知道这里可能是什么问题?

Your solution wouldn't work, because you're always creating a new instance of the manager.您的解决方案不起作用,因为您总是在创建管理器的实例。

Whenever I need to rely on some "global" objects in a Qt program, I usually create a subclass of the QApplication and create attributes for them, which obviously also works for "global signals".每当我需要依赖 Qt 程序中的一些“全局”对象时,我通常会创建 QApplication 的子类并为它们创建属性,这显然也适用于“全局信号”。

Then you can emit the signals or connect to them by accessing the application instance() :然后您可以通过访问应用程序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()

An alternative could be to use a global QObject subclass in a separate module, using a reference that is global to the module corresponding to a unique instance (one of the rare cases for which using global actually makes sense).另一种方法是在单独的模块中使用全局 QObject 子类,使用对对应于唯一实例的模块的全局引用(使用global实际上有意义的罕见情况之一)。

A possible "hacky" implementation would be to create a function named as the signal manager, and replace its global reference with an instance of the QObject, like the following example:一个可能的“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()

The above could obviously be achieved with a singleton class too.以上显然也可以通过单例类来实现。

In any case, I wouldn't suggest this practice, as I believe that the QApplication subclass would be better for many reasons, including the fact that it's more appropriate for the OOP pattern.无论如何,我不建议这种做法,因为我相信 QApplication 子类会更好,原因有很多,包括它更适合 OOP 模式。

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

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