0

I'm running a QWidget in python using an extended version of the following code:

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.hello_world)
        self.timer.start(10000)

    
    def hello_world(self):
        print("Hello world")

class MyMainWindow(QMainWindow):
    def __init__(self, gates, **kwargs):
        super().__init__()
        self.widget = MyWidget()
        self.setCentralWidget(self.widget)

def _run_app(stop_event, widget_queue):
    _toggle_lock()
    app = QApplication(sys.argv)
    main_widget = InteractiveWindow()
    main_widget.show()
    widget_queue.put(main_widget.widget)
    print("GUI running")
 
    app.aboutToQuit.connect(_toggle_lock)
    while not stop_event.is_set():
        app.processEvents()
    app.quit()
    _toggle_lock(False)

def _toggle_lock(state=None):    
    global LOCK
    if state is None:
        LOCK = not LOCK
    else:
        LOCK = state    

def open_gui():
    if not LOCK:
        stop_event = threading.Event()
        widget_queue = queue.Queue()
        gui_thread = threading.Thread(target=_run_app, args=(stop_event, widget_queue), daemon=True)
        gui_thread.start()
        return gui_thread, stop_event, widget_queue.get()
    else:
        print("GUI is already running")

def close_gui(gui_thread, stop_event):
    if gui_thread.is_alive():
        stop_event.set()
        gui_thread.join()

Once I start up the widget from a python script using thread, stop, widget = open_gui(), the timer runs as expected printing "Hello world" every 10 seconds. I can also stop it from the notebook using widget.timer.stop() and it will stop printing. The problem comes when I try to restart the timer by calling widget.timer.start(10000), nothing happens.

I would like to find a way to restart the timer from outside its thread.

2
  • 1
    Qt does not support GUI operations of any kind outside the main thread. And in any case, the way threading is used in the example is both pointless and wrong. Your question currently looks like an XY Problem, so you should explain what you are actually trying to achieve, rather than asking how to "fix" such badly designed code. Commented Mar 10 at 11:35
  • The timer is only apparently stopped, in reality it just keeps going without doing anything (including emitting timeout). If you run the code in a terminal or prompt you should be able to see warnings when trying to call both stop() and start(). So, even if stop() seems to work, it's inappropriate to use it from external threads just like it's not possible to call start(), as the QTimer documentation clearly explains. In general, the UI thread should always be the main one, doing the opposite (and trying to work around it) is almost always due to poor design. Commented Mar 10 at 19:19

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.