The question has been asked before and I want to put forward my solution and wonder if this is an acceptable pattern or is there a better alternative.
Working with QGIS I started to work with PyQt as a GUI (previously mostly tkinter) and I have a situation where I make a selection on the canvas that then opens another window to give information on the features. On the canvas I want to mark the selected feature, so information is required from the other window.
I made a minimal working example in PyQt below (required import PyQt5 with Python 3.8) where I have two windows one called Button and the other Display where Display shows how many times the button is pressed.
To make the communication I defined a QTimer in the Display window that polls the Button window (in this case every 250 ms) to get the required information. Question is there a better way to do this in 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()