如何解决PyQt:在窗口之间传递信息
这个问题已经被问过了,我想提出我的解决方案,想知道这是可以接受的模式还是有更好的选择。
使用QGIS我开始使用PyQt作为GUI(以前主要是tkinter),并且遇到了这样的情况:我在画布上进行选择,然后打开另一个窗口以提供有关功能的信息。我要在画布上标记选定的功能,因此需要其他窗口提供信息。
我在下面的PyQt中做了一个最小的工作示例(需要使用Python 3.8导入PyQt5),其中有两个窗口,一个叫做Button
,另一个是Display
,其中Display
显示了多少次该按钮被按下。
为了进行通信,我在QTimer
窗口中定义了一个Display
,该窗口会轮询Button
窗口(在这种情况下,每250 ms)以获取所需的信息。问题是在PyQt中有更好的方法吗?
import sys
from PyQt5.QtWidgets import QWidget,QVBoxLayout,QLabel,QApplication,QPushButton
from PyQt5.QtCore import QTimer
POLL_INTERVAL = 250 # in ms
WINSIZE = (200,50) # w,h
BUTTON_WIN_POS = (200,200) # w,h
DISPLAY_WIN_POS = (450,h
class ButtonWindow(QWidget):
def __init__(self):
super().__init__()
self.button_pressed_counter = 0
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
button = QPushButton('Press me')
button.clicked.connect(self.press_button)
vbox.addWidget(button)
self.setLayout(vbox)
self.move(*BUTTON_WIN_POS)
self.setWindowTitle('Button ... ')
self.resize(*WINSIZE)
self.show()
def press_button(self):
self.button_pressed_counter += 1
@property
def button_count(self):
return self.button_pressed_counter
class DisplayWindow(QWidget):
def __init__(self):
super().__init__()
self.button_window = ButtonWindow()
self.button_count = 0
self.button_counter = QTimer()
self.button_counter.timeout.connect(self.get_button_count)
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
self.text_lbl = QLabel()
vbox.addWidget(self.text_lbl)
self.text_lbl.setText(f'button count: {self.button_count}')
self.setLayout(vbox)
self.move(*DISPLAY_WIN_POS)
self.setWindowTitle('Display ... ')
self.resize(*WINSIZE)
self.show()
self.button_counter.start(POLL_INTERVAL)
def get_button_count(self):
new_button_count = self.button_window.button_count
if self.button_count == new_button_count:
pass
else:
self.button_count = new_button_count
self.text_lbl.setText(f'button count: {self.button_count}')
def main():
app = QApplication([])
_ = DisplayWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
解决方法
不是,至少在这种情况下,这不是一个好的解决方案。另外,在处理交互式元素时,依靠计时器进行“轮询”很少是一个好的解决方案:它不可靠,不允许单击的按钮和结果之间立即做出响应,并且使代码不必要地复杂。
信号和插槽正是为此目的而存在的:允许对象之间通信的通用接口;因此请在“源”类中实现自定义信号,然后将其连接到“目标”中。
class ButtonWindow(QWidget):
pressCountChanged = pyqtSignal(int)
# ...
def press_button(self):
self.button_pressed_counter += 1
self.pressCountChanged.emit(self.button_pressed_counter)
class DisplayWindow(QWidget):
def __init__(self):
super().__init__()
self.button_window = ButtonWindow()
self.button_window.pressCountChanged.connect(self.get_button_count)
self.button_count = 0
self.initUI()
显然,必须删除与QTimer相关的所有内容。
请注意,如果您正在使用另一个窗口获取应更改主界面行为的“功能”,则应考虑改用QDialog,并最终决定是否将其用作模式(通常通过{{ 1}}),它可以在关闭对话框之前阻止与其他窗口的交互,并(可能)返回所需的值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。