在 PyQt5 中,为什么 Signal 不能连接外部的 Slot class?
In PyQt5, Why Signal can't connect a Slot in a external class?
背景
我正在使用信号在 PyQt5 中实现 MVC。一个程序中有多个接口。每个页面都有对应的controller,所有的controller最后放在一起。
问题
我的问题是:我在四个不同的地方实现了相同的插槽功能,但是为什么Signal不能连接外部的插槽class?
这是目录树:
error
├─ UI
│ └─ main_window.py
├─ control
│ ├─ controller.py
│ └─ login_control.py
├─ main.py
└─ model
└─ model.py
最小可运行示例
model.py:
class Student(object):
def __init__(self):
self.name = "aaa"
self.password = "aaa"
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:
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
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
没有输出,我应该如何解决呢?这个问题困扰了我半个月,谢谢
没有对 login_controller
的持久引用:您将其创建为 local 变量,然后 init
函数 returns,python的垃圾收集器无法找到对它的任何引用,因此将其删除。
解决方法很简单:
def init(self):
<b>self.login_controller</b> = login_control.Controller(
self._view, self._stu.name, self._stu.password)
self._view.login_signal.connect(self.login)
请考虑,虽然使用 MVC 模式通常是个好主意,但应该通过提供更好的抽象和提供更容易的调试而不会使事情过于复杂来提高项目结构的质量。
例如,您的 Controller
class(它的名字也确实 太 类似于另一个),几乎是多余的,因为您的主要 Controll
应该够了。
背景
我正在使用信号在 PyQt5 中实现 MVC。一个程序中有多个接口。每个页面都有对应的controller,所有的controller最后放在一起。
问题
我的问题是:我在四个不同的地方实现了相同的插槽功能,但是为什么Signal不能连接外部的插槽class?
这是目录树:
error
├─ UI
│ └─ main_window.py
├─ control
│ ├─ controller.py
│ └─ login_control.py
├─ main.py
└─ model
└─ model.py
最小可运行示例
model.py:
class Student(object):
def __init__(self):
self.name = "aaa"
self.password = "aaa"
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:
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
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
没有输出,我应该如何解决呢?这个问题困扰了我半个月,谢谢
没有对 login_controller
的持久引用:您将其创建为 local 变量,然后 init
函数 returns,python的垃圾收集器无法找到对它的任何引用,因此将其删除。
解决方法很简单:
def init(self):
<b>self.login_controller</b> = login_control.Controller(
self._view, self._stu.name, self._stu.password)
self._view.login_signal.connect(self.login)
请考虑,虽然使用 MVC 模式通常是个好主意,但应该通过提供更好的抽象和提供更容易的调试而不会使事情过于复杂来提高项目结构的质量。
例如,您的 Controller
class(它的名字也确实 太 类似于另一个),几乎是多余的,因为您的主要 Controll
应该够了。