My electronic scoreboard program for competitions has a long process of recording data in excel, so that the interface does not freeze, I use multithreading. Under certain conditions, after recording in Excel, one application window should close and another should open. that is, the created thread must pass information to the main thread, which is now the case when another window needs to be opened. But I don’t know how to pass this information so that:
- the interface did not freeze (because multithreading is not used)
- a second window opened (the main window opens, but the other one does not, because the method is not called from the main thread)
It is very important that the interface does not freeze while the function is running
Below I will show you a simplified representation, where:
- the
MainWindow.foo()
method creates a thread with thewriteToExcel
function simulating writing to an excel file and fulfilling the condition for opening another window (making sure that the condition is always satisfied)
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import QTimer
import threading
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Main Window")
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
layout = QVBoxLayout()
self.central_widget.setLayout(layout)
self.label = QLabel("00:00:00")
layout.addWidget(self.label)
self.button = QPushButton("Open Secondary Window")
self.button.clicked.connect(self.open_secondary_window)
layout.addWidget(self.button)
self.label2 = QLabel("foo not runned")
layout.addWidget(self.label2)
self.button2 = QPushButton("Run foo()")
self.button2.clicked.connect(self.foo)
layout.addWidget(self.button2)
self.timer = QTimer()
self.timer.timeout.connect(self.update_stopwatch)
self.time_elapsed = 0
self.start_stopwatch() # Start the stopwatch when the window is created
def open_secondary_window(self):
self.secondary_window = SecondaryWindow()
self.close()
self.secondary_window.show()
def update_stopwatch(self):
self.time_elapsed += 1
hours = self.time_elapsed // 3600
minutes = (self.time_elapsed // 60) % 60
seconds = self.time_elapsed % 60
self.label.setText(f"{hours:02d}:{minutes:02d}:{seconds:02d}")
def start_stopwatch(self):
self.timer.start(1000)
def stop_stopwatch(self):
self.timer.stop()
def foo(self):
if threading.activeCount() <= 1:
thread1 = threading.Thread(target=self.writeToExcel, daemon=True)
thread1.start()
else:
self.label2.setText('foo still running')
def writeToExcel(self):
self.label2.setText('foo is run')
time.sleep(5)
self.label2.setText('foo was done')
time.sleep(1)
if True:
self.open_secondary_window()
class SecondaryWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Secondary Window")
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
layout = QVBoxLayout()
self.central_widget.setLayout(layout)
self.button = QPushButton("Open Main Window")
self.button.clicked.connect(self.open_main_window)
layout.addWidget(self.button)
def open_main_window(self):
self.main_window = MainWindow()
self.close()
self.main_window.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())