在 PyQt5 中,为什么 Signal 无法连接外部类中的 Slot? [英] In PyQt5, Why Signal can't connect a Slot in a external class?

查看:105
本文介绍了在 PyQt5 中,为什么 Signal 无法连接外部类中的 Slot?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用信号在 PyQt5 中实现 MVC.一个程序中有多个接口.每个页面都有一个对应的控制器,最后所有的控制器组合在一起.

I'm using signals to implement MVC in PyQt5. There are many interfaces in one program. Each page has a corresponding controller, and all the controllers are finally put together.

我的问题是:我在四个不同的地方实现了相同的slot函数,但是为什么Signal不能连接外部类中的slot?

My question is : I implemented the same slot function in four different places, but Why Signal can't connect a Slot in a external class ?

这是目录树:

error
├─ UI
│    └─ main_window.py
├─ control
│    ├─ controller.py
│    └─ login_control.py
├─ main.py
└─ model
       └─ model.py

最小的可运行示例

model.py:

minimal runnable example

model.py:

class Student(object):

    def __init__(self):
        self.name = "aaa"
        self.password = "aaa"

login_control.py:

login_control.py:

class Controller(object):
    def __init__(self, view, stu_id, stu_psd):
        self._view = view
        self._stu_id = stu_id
        self._stu_psd = stu_psd
        self.init()

    def init(self):
        # connect successfully
        self._view.login_signal.connect(self._view.login)
        # Connection failed  why ???
        self._view.login_signal.connect(self.login)

        # connect successfully
        self._view.login_signal.connect(login)

    # why this failed ???
    def login(self):
        print('222')

def login():
    print('333')

controller.py:

controller.py:

import sys
from PyQt5.QtWidgets import QApplication
from model.model import Student
from UI.main_window import MainWindow
from control import login_control


class Controll(object):

    def __init__(self):

        self._app = QApplication([])

        self._stu = Student()

        self._view = MainWindow()
        self.init()

    def init(self):
        login_controller = login_control.Controller(self._view, self._stu.name, self._stu.password)
        # connect successfully
        self._view.login_signal.connect(self.login)

    def login(self):
        print('444')

    def run(self):
        self._view.show()
        return self._app.exec()

main_window.py

main_window.py

from PyQt5.QtWidgets import QWidget, QHBoxLayout, QPushButton, QMessageBox, QLineEdit
from PyQt5 import QtCore


class MainWindow(QWidget):
    login_signal = QtCore.pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.id_line = QLineEdit()
        self.id_line.setPlaceholderText("Please Input ID")
        self.psd_line = QLineEdit()
        self.psd_line.setPlaceholderText("Please Input Password")

        self.init()

    def init(self):

        layout = QHBoxLayout()
        self.setLayout(layout)

        self.button = QPushButton("Login")
        layout.addWidget(self.button)

        layout.addWidget(self.id_line)
        layout.addWidget(self.psd_line)
    
        self.button.clicked.connect(self.login_signal)

    def login(self):
        print('111')

    def verify_ok(self):
        QMessageBox.about(self, "Correct", "Login successfully")

    def verify_no(self):
        QMessageBox.about(self, "Mistake", "Input again")

main.py

import sys
from control.controller import Controll


if __name__ == "__main__":
    controller = Controll()
    sys.exit(controller.run())

python main.py,输出为:

111
333
444

我想要的输出是:

111
222
333
444

我想验证 login 函数中的信息.但是为什么 222 没有输出,我该怎么做才能解决呢?这个问题困扰了我半个月,谢谢.

I want to verify the info in login function. But why 222 is not output, and what should I do to fix it? This problem has bothered me for half a month, thank you.

推荐答案

没有对 login_controller 的持久引用:您将其创建为 local 变量,然后 init 函数返回,python 的垃圾收集器找不到对它的任何引用,因此将其删除.

There is no persistent reference to login_controller: you create it as a local variable, then the init function returns, python's garbage collector is unable to find any reference to it, so it deletes it.

解决方案很简单:

    def init(self):
        self.login_controller = login_control.Controller(
            self._view, self._stu.name, self._stu.password)
        self._view.login_signal.connect(self.login)

请注意,虽然使用 MVC 模式通常是一个好主意,但应该通过提供更好的抽象和更容易的调试来提高项目结构的质量.
例如,您的 Controller 类(它的名称也与另一个类 非常相似)几乎是多余的,因为您的主要 Controll应该足够了.

Please consider that, while using an MVC pattern is generally a good idea, it should be done to improve the quality of your project structure by providing better abstraction and offering easier debugging without overcomplicating things.
For instance, your Controller class (which also has a name that is really too similar to the other one), is almost superfluous, as your main Controll should be enough.

这篇关于在 PyQt5 中,为什么 Signal 无法连接外部类中的 Slot?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆