在 PyQt5 中,为什么 Signal 无法连接外部类中的 Slot? [英] In PyQt5, Why Signal can't connect a Slot in a external class?
问题描述
我正在使用信号在 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屋!