Python PyQt:在窗口之间传递信息
以前有人问过这个问题,我想提出我的解决方案,想知道这是一种可以接受的模式,还是有更好的替代方案 使用QGIS时,我开始使用PyQt作为GUI(以前主要是tkinter),我在画布上进行选择,然后打开另一个窗口提供有关功能的信息。在画布上,我想标记所选的特征,因此需要从另一个窗口获取信息 我在下面的PyQt中做了一个最小的工作示例(需要使用Python 3.8导入PyQt5),其中我有两个窗口,一个叫做Python PyQt:在窗口之间传递信息,python,pyqt,qgis,Python,Pyqt,Qgis,以前有人问过这个问题,我想提出我的解决方案,想知道这是一种可以接受的模式,还是有更好的替代方案 使用QGIS时,我开始使用PyQt作为GUI(以前主要是tkinter),我在画布上进行选择,然后打开另一个窗口提供有关功能的信息。在画布上,我想标记所选的特征,因此需要从另一个窗口获取信息 我在下面的PyQt中做了一个最小的工作示例(需要使用Python 3.8导入PyQt5),其中我有两个窗口,一个叫做按钮,另一个叫做显示,其中显示显示按钮被按下的次数 为了进行通信,我在显示窗口中定义了一个QTi
按钮
,另一个叫做显示
,其中显示
显示按钮被按下的次数
为了进行通信,我在显示
窗口中定义了一个QTimer
,它轮询按钮
窗口(在这种情况下,每250毫秒一次),以获取所需信息。问题是在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, 200) # w, 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()
不,至少在这种情况下,这不是一个好的解决方案。此外,在处理交互元素时,依靠计时器“轮询”很少是一个好的解决方案:它不可靠,不允许在单击的按钮和结果之间立即响应,并且使代码变得不必要的复杂 信号和插槽的存在正是为了这个目的:一个公共接口,允许对象之间的通信;因此,在“source”类中实现一个自定义信号,并将其连接到“target”中 显然,必须删除与QTimer相关的所有内容
请注意,如果你使用另一个窗口来获得“特征”,它应该改变主界面的行为,你应该考虑使用Q对话框,并最终决定是否使用它作为模式(通常是通过<代码> Excel())/>代码>,这阻止了与其他窗口的交互,直到对话框关闭,并且(可能)返回所需的值。不,至少在这种情况下,这不是一个好的解决方案。此外,在处理交互元素时,依靠计时器“轮询”很少是一个好的解决方案:它不可靠,不允许在单击的按钮和结果之间立即响应,并且使代码变得不必要的复杂 信号和插槽的存在正是为了这个目的:一个公共接口,允许对象之间的通信;因此,在“source”类中实现一个自定义信号,并将其连接到“target”中 显然,必须删除与QTimer相关的所有内容
请注意,如果你使用另一个窗口来获得“特征”,它应该改变主界面的行为,你应该考虑使用Q对话框,并最终决定是否使用它作为模式(通常是通过<代码> Excel())/>代码>,这阻止了与其他窗口的交互,直到对话框关闭,并且(可能)返回所需的值。Great answet,直截了当,介绍了正确的概念,并提供了一个简单的示例:)非常好,非常感谢。我觉得会有更好的解决方案。伟大的answet,直截了当地介绍了正确的概念,还有一个简单的例子:)非常好,非常感谢。我觉得会有更好的解决办法。
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()