QSystemTrayIcon导致PySide2程序崩溃,Windows报AppHangB1无控制台错误
I've run into this exact silent AppHangB1 crash with QSystemTrayIcon in PySide2 before—super frustrating since there’s no console output to debug with. Looking at your code, the issues are almost certainly tied to Qt object lifecycle management (a common pitfall in Python-Qt bindings where Python’s garbage collection clashes with Qt’s ownership rules). Here’s what to fix:
1. Give QMenu a Proper Parent (Critical Fix)
Your QMenu instance doesn’t have a parent set, which means Python’s garbage collector might clean it up right after you call setContextMenu()—especially if the menu isn’t shown immediately. When you try to open the tray menu later, you’re accessing a destroyed object, which triggers the silent crash.
Fix:
class SystemTrayIcon(QSystemTrayIcon): def __init__(self, icon, parent=None): QSystemTrayIcon.__init__(self, icon, parent) # Assign the tray icon as the menu's parent to tie their lifecycles menu = QMenu(self) showAction = menu.addAction("Fenster anzeigen") exitAction = menu.addAction("Beenden") # ... rest of your menu styling ... self.setContextMenu(menu)
2. Ditch Global Variables for Class Attributes
Your code relies heavily on global variables for UI elements (loading_screen, kunden_screen, etc.). This makes it impossible to track object ownership and can lead to Qt objects being destroyed while still referenced elsewhere.
Fix:
Store these UI elements as instance attributes instead. For example, in your LoadingScreen class:
class LoadingScreen(QWidget): def __init__(self): super(LoadingScreen, self).__init__() loader = QUiLoader() file = QFile("loading_screen.ui") file.open(QFile.ReadOnly) # Store as self attribute instead of global self.loading_screen = loader.load(file, self) file.close() self.initUI() # ... rest of your code ...
Do the same for KundenSelect and CancelWindow. Use signals and slots to communicate between components instead of relying on globals.
3. Replace sys.exit() with Qt’s Proper Quit Method
Calling sys.exit() directly from your tray’s exit action bypasses Qt’s cleanup process. This leaves Qt objects in an inconsistent state, which can trigger hangs or crashes.
Fix:
def exit(self): # Tell Qt to properly shut down the application and clean up all objects QCoreApplication.instance().quit()
4. Verify Thread Safety in Your Config Thread
While your config thread doesn’t seem to touch UI elements directly, always remember: Qt UI operations must only happen in the main thread. If your thread ever needs to update UI state (e.g., signal that config is done), use Qt signals and slots to communicate with the main thread—never modify UI objects directly in run().
Also, store the thread as an instance attribute of LoadingScreen so it doesn’t get GC’d prematurely.
5. Double-Check UI Loader Parenting
When using QUiLoader.load(), ensure you’re passing the correct parent widget. In your code, passing self (the parent QWidget) is correct, but make sure none of your UI elements have conflicting parent relationships that could cause premature destruction.
After making these changes, the AppHangB1 crash should disappear. The core issue is ensuring all Qt objects have clear parent-child relationships so Qt (and Python) know when to clean them up properly.
内容的提问来源于stack exchange,提问作者dhirczy87

