PySide6 gets stuck in QtWidget.setVisible()
-
Hi there!
I'm attempting to develop a python program in which I want to use the PySide6 Dialog to obtain user input. To ensure the main program does not terminate (
pynput keyboard.Listener
) after the dialog is closed, I placed my PySide6 Dialog function in a thread pool. It works well when I first time call the dialog in my code; however, when I try to call it again, the dialog window fails to show. Upon further inspection, I found that it gets stuck in theQtWidget.setVisible()
method. Does anyone know why or can help me solve this problem? Thanks!from PySide6.QtWidgets import QWidget, QApplication import sys from concurrent.futures import ThreadPoolExecutor from mini_dialog import Ui_Dialog # Just an empty Dialog class MyQWidget(QWidget): def __init__(self): super().__init__() def setVisible(self, visible): print("setVisible...[stuck here]") return super().setVisible(visible) class MyWidget(MyQWidget, Ui_Dialog): def __init__(self, app): super().__init__() self.setupUi(self) self.app = app self.message = {} def show(self): print("show...") # return super().show() self.setVisible(True) def run_my_weight(): app = QApplication.instance() if app is None: app = QApplication(sys.argv) widget = MyWidget(app) widget.show() print("first time is ok") app.exec() return widget.message def main(): with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(run_my_weight) result = future.result() print(result) if __name__ == '__main__': main() main()
Output: No error or more information.
show... setVisible...[stuck here] first time is ok setVisible...[stuck here] {} show... setVisible...[stuck here]
-
@LingHan said in PySide6 gets stuck in QtWidget.setVisible():
I should redesign my program and use front-end code to call my back end algorithms, rather than the other way around.
Yes. You should create a single
QApplication
instance and callQApplication.exec()
as the last step frommain()
. It does not return until the user quits. All your UI code must be in the main thread, the one where theQApplication
is created. You can do background/computation code in secondary threads, either long running one(s) or short-lived. The Qt thread code runs an event loop in each thread, so you can send it signals (e.g. to start something off) and it can send signals back to your main (e.g. when it has finished something or wants the UI to show something on its behalf). -
@LingHan said in PySide6 gets stuck in QtWidget.setVisible():
I placed my PySide6 Dialog function in a thread pool.
This is not allowed. Qt requires all UI stuff to be done in the main thread only. Period. You are seeing the consequences of not.
Do back end stuff in a thread, if you need to. Communicate with UI only through signals & slots.
from concurrent.futures import ThreadPoolExecutor
Consider using Qt's threading instead of Python's for a Qt application. Not mandatory, I think, but might have advantages.
You seem to be creating a
QApplication
and executingQApplication.exec()
each time in some thread? That is not the way to do things. You should not be doing any such even if sequential/serial, but certainly not in parallel. -
Oh, thank you!
Actually, this is my first Qt application. I initially thought I could treat the Qt Dialog as a lightweight component within my program. Whenever my back-end code needed to get input, I could just call it, close it, and repeat. But that is wrong.
I should redesign my program and use front-end code to call my back end algorithms, rather than the other way around.
Appreciate it!
-
-
@LingHan said in PySide6 gets stuck in QtWidget.setVisible():
I should redesign my program and use front-end code to call my back end algorithms, rather than the other way around.
Yes. You should create a single
QApplication
instance and callQApplication.exec()
as the last step frommain()
. It does not return until the user quits. All your UI code must be in the main thread, the one where theQApplication
is created. You can do background/computation code in secondary threads, either long running one(s) or short-lived. The Qt thread code runs an event loop in each thread, so you can send it signals (e.g. to start something off) and it can send signals back to your main (e.g. when it has finished something or wants the UI to show something on its behalf). -