如何将一个模块内的类中的 pyqtSignal 连接到另一个模块内的类中的 pyqtSlot?

Posted

技术标签:

【中文标题】如何将一个模块内的类中的 pyqtSignal 连接到另一个模块内的类中的 pyqtSlot?【英文标题】:How to connect a pyqtSignal from a class inside one module to a pyqtSlot in a class inside another module? 【发布时间】:2020-07-13 18:47:14 【问题描述】:

我有一个文件wizard.py:

class MyWizard(QWizard):
    def __init__(self):
        super().__init__()
        # ...

class PageOne(QWizardPage):
    def __init__(self):
        super().__init__()
        # ...

class FinalPage(QWizardPage):
    populateTable = pyqtSignal()

    def __init__(self):
        super().__init__()
        # ...

    def initializePage(self):
        finish_button = self.wizard().button(QWizard.FinishButton)
        finish_button.clicked.connect(self.populateTable.emit)

还有另一个文件main_ui.py:

import wizard

class UiMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.table = QTableView(self)
        # ...

        self.my_wizard = wizard.MyWizard()
        self.my_wizard.exec_()
        # ...

        self.final_page = wizard.FinalPage()
        self.final_page.connect(self.populate_table)

    @pyqtSlot()
    def populate_table(self):
        # fill some data into self.table

main_ui 模块导入wizard 模块并启动向导。

启动向导后,我想在每次单击向导的完成按钮时在最后一页关闭向导时调用main_ui.py 中的populate_table() 方法。

我尝试从向导发出pyqtSignal() 并将其连接到UiMainWindowpopulate_table() 方法,但它似乎没有收到信号。我在populate_table() 上使用了@pyqtSlot() 装饰器,但这也不起作用。

但是,从我连接到populate_table() 的自定义类内部 main_ui.py 发出信号可以正常工作。但是没有收到来自wizard.py 内部类的信号。

我的问题:

有没有办法将来自一个模块中的类的信号连接到另一个模块中的类的方法

【问题讨论】:

“发出一个`pyqtSignal()”是什么意思?我在您的课程中没有看到任何 pyqtSignal 声明。 Qt 信号必须在类定义中声明。 我已经编辑了我的问题。 @Joey 更改为 self.final_page.populateTable.connect(self.populate_table) @Joey 连接语法为:sender.signal.connect(obj.slot) @Joey:在您发布的示例中,self.final_page = wizard.FinalPage() 将创建一个新的FinalPage 实例,该实例独立于self.my_wizard 中的最后一页。您需要将插槽连接到在self.my_wizard 中显示的FinalPage 实例的信号。您最好将信号 populateTableFinalPage 移动到 Wizard 并在 UiMainWindow 中将 self.my_wizard.populateTable 连接到 self.populate_table 【参考方案1】:

正如@Heike 所建议的,信号必须定义在MyWizard 而不是FinalPage

那么self.my_wizard.populateTable信号必须连接到UiMainwindow中的self.populate_table方法。

想要在FinalPage 中使用finish_button 来发出信号已经是一个坏主意,因为之前我已经将finish_buttonself.wizard().restart() 连接起来,这是必要的,因为向导已执行来自UiMainwindow。这意味着没有调用self.wizard().restart(),下次执行时(即FinalPage)向导将始终在最后一个活动页面上重新生成。

所以,为了发送信号,我现在在FinalPageinitializePage 方法中调用self.wizard().populateTable.emit(),然后如上所述在UiMainWindow 中使用populate_table 方法连接它。


我已经相应地重写了代码:

wizard.py

class MyWizard(QWizard):
    populateTable = pyqtSignal()

    def __init__(self):
        super().__init__()
        # ...

class PageOne(QWizardPage):
    def __init__(self):
        super().__init__()
        # ...

class FinalPage(QWizardPage):
    def __init__(self):
        super().__init__()
        # ...

    def initializePage(self):
        # need to keep finish_button connected to self.wizard().restart()
        finish_button = self.wizard().button(QWizard.FinishButton)
        finish_button.clicked.connect(self.wizard().restart)

        # emit the signal when switching to the last page
        self.wizard().populateTable.emit()

ma​​in_ui.py

import wizard

class UiMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.table = QTableView(self)
        # ...

        self.my_wizard = wizard.MyWizard()
        self.my_wizard.populateTable.connect(self.populate_table)
        # ...

    def populate_table(self):
        # update the content in self.table

【讨论】:

以上是关于如何将一个模块内的类中的 pyqtSignal 连接到另一个模块内的类中的 pyqtSlot?的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖模块中的类常量和方法?

如何将引用模块中字段的匿名提供者移动到单独的类中?

如何将 PyQt 插槽从后台线程连接到 gui 线程

lambda中对象的生命周期连接到pyqtSignal

表单类型类中的类约束验证器?

如何获取存储在数组中的类中的值?