Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Hiding main window on starting, showing later causes "QObject::setParent: Cannot set parent, new parent is in a different thread"
Forum Update on Monday, May 27th 2025

Hiding main window on starting, showing later causes "QObject::setParent: Cannot set parent, new parent is in a different thread"

Scheduled Pinned Locked Moved Solved Qt for Python
9 Posts 2 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    donbfry
    wrote on last edited by
    #1

    Hello. I am trying to start my app in the system tray only and then show the window later using global shortcuts.

    Below is my sample code. I am using Python 3.10.0, PySide6 6.2.2.1, and a package for global shortcuts called "keyboard" which you can install using pip install keyboard.

    Qt Designer UI File (testui.py):

    # -*- coding: utf-8 -*-
    
    ################################################################################
    ## Form generated from reading UI file 'testui.ui'
    ##
    ## Created by: Qt User Interface Compiler version 6.2.2
    ##
    ## WARNING! All changes made in this file will be lost when recompiling UI file!
    ################################################################################
    
    from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
        QMetaObject, QObject, QPoint, QRect,
        QSize, QTime, QUrl, Qt)
    from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
        QFont, QFontDatabase, QGradient, QIcon,
        QImage, QKeySequence, QLinearGradient, QPainter,
        QPalette, QPixmap, QRadialGradient, QTransform)
    from PySide6.QtWidgets import (QApplication, QGridLayout, QLabel, QMainWindow,
        QSizePolicy, QWidget)
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            if not MainWindow.objectName():
                MainWindow.setObjectName(u"MainWindow")
            MainWindow.resize(500, 300)
            self.centralwidget = QWidget(MainWindow)
            self.centralwidget.setObjectName(u"centralwidget")
            sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
            self.centralwidget.setSizePolicy(sizePolicy)
            self.gridLayout = QGridLayout(self.centralwidget)
            self.gridLayout.setObjectName(u"gridLayout")
            self.testLabel = QLabel(self.centralwidget)
            self.testLabel.setObjectName(u"testLabel")
            font = QFont()
            font.setFamilies([u"Segoe UI"])
            font.setPointSize(22)
            self.testLabel.setFont(font)
            self.testLabel.setAlignment(Qt.AlignCenter)
    
            self.gridLayout.addWidget(self.testLabel, 0, 0, 1, 1)
    
            MainWindow.setCentralWidget(self.centralwidget)
    
            self.retranslateUi(MainWindow)
    
            QMetaObject.connectSlotsByName(MainWindow)
        # setupUi
    
        def retranslateUi(self, MainWindow):
            MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
            self.testLabel.setText(QCoreApplication.translate("MainWindow", u"TEST WINDOW", None))
        # retranslateUi
    

    Main.py File:

    import sys
    import ctypes
    import PySide6
    import keyboard
    
    from PySide6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
    from PySide6.QtGui import QIcon, QAction
    from testui import Ui_MainWindow
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            QMainWindow.__init__(self)
    
            # Setup UI from Qt Designer generated file.
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            self.title = "Test Window"
            self.setWindowTitle(self.title)
    
            # Initial state of MainWindow.
            self.is_maximized = False
    
            # Show window here. Will be hidden later.
            self.show()
    
        def maximize_window(self):
            if self.is_maximized:
                return
            else:
                user32 = ctypes.WinDLL("user32")
                hwnd = user32.FindWindowW(None, self.title)
                user32.ShowWindow(hwnd, 9)
                self.showNormal()
                self.is_maximized = True
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MainWindow()
    
        # Hide window after initializing.
        window.hide()
    
        # System tray.
        icon = QIcon("tray_icon.ico")
    
        system_tray = QSystemTrayIcon()
        system_tray.setIcon(icon)
    
        tray_menu = QMenu()
    
        tray_quit = QAction("Quit")
        tray_quit.triggered.connect(app.quit)
        tray_menu.addAction(tray_quit)
    
        system_tray.setContextMenu(tray_menu)
    
        system_tray.show()
    
        # Global Shortcuts
        keyboard.add_hotkey("ctrl+alt+t", lambda: window.maximize_window())
    
        sys.exit(app.exec())
    

    My assumption is there is a better way to start an application only in the system tray but I did not have any luck researching the topic or figuring out a different way to do so other than what I am currently doing. I first show the window as the class in created but then hide it right after. The global shortcut calls a method that uses ctypes to find the window, bring it to the front, and then call show(). This was the only way I could get it to work but it still gives the error QObject::setParent: Cannot set parent, new parent is in a different thread.

    When I researched into this error I mostly saw posts about calling GUI methods from outside the main GUI thread. I don't believe I am doing so unless my understanding of how the QMainWindow works with show() and hide(). I was thinking maybe it was the global shortcut function that is calling the maximize_window() method outside the GUI thread but moving it inside the __init__() of MainWindow did not resolve the issue.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      donbfry
      wrote on last edited by donbfry
      #7

      After beating my head against a wall for hours on end trying numerous things, I finally got it to work with no errors. Here is the updated code:

      import keyboard
      import ctypes
      
      from PySide6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
      from PySide6.QtGui import QIcon, QAction
      from testui import Ui_MainWindow
      
      
      class MainWindow(QMainWindow):
          def __init__(self):
              QMainWindow.__init__(self)
      
              # Setup UI from Qt Designer generated file.
              self.ui = Ui_MainWindow()
              self.ui.setupUi(self)
      
              self.title = "Test Window"
              self.setWindowTitle(self.title)
      
              # Initial state of MainWindow.
              self.is_maximized = False
      
              # Create QAction with a trigger for restoring window.
              restore_window = QAction("Restore Window")
              restore_window.triggered.connect(self.maximize_window)
      
              # Global shortcut triggers QAction.
              keyboard.add_hotkey("ctrl+alt+t", restore_window.trigger)
      
          def maximize_window(self):
              if self.is_maximized:
                  print("Already maximized.")
                  return
              else:
                  self.show()
                  self.is_maximized = True
      
                  user32 = ctypes.WinDLL("user32")
                  hwnd = user32.FindWindowW(None, self.title)
                  user32.ShowWindow(hwnd, 9)
      
          def closeEvent(self, event):
              self.is_maximized = False
              return super().closeEvent(event)
      
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
          app.setQuitOnLastWindowClosed(False)
      
          window = MainWindow()
      
          # Hide window after initializing.
          window.show()
          window.hide()
      
          # System tray.
          icon = QIcon("tray_icon.ico")
      
          system_tray = QSystemTrayIcon()
          system_tray.setIcon(icon)
      
          tray_menu = QMenu()
      
          tray_quit = QAction("Quit")
          tray_quit.triggered.connect(app.quit)
          tray_menu.addAction(tray_quit)
      
          system_tray.setContextMenu(tray_menu)
      
          system_tray.show()
      
          sys.exit(app.exec())
      

      I created a QAction with a trigger and on press of the global shortcut, manually triggers the QAction. The trigger shows the window minimized (even those I'm not calling showMinimized() which is interesting). This is where ctypes comes in to bring it to the front.

      I've attempted to use Slots and Signals to get this to work and it did not so I'm not sure why a QAction trigger.

      SGaistS 1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        On which OS are you running that code ?

        On a side note, don't call show in the constructor of your widget. It's bad practice. You even call hide directly after the construction which you would not need to do in the first place. Widgets shall not be responsible for showing themselves upon construction, it's the responsibility of the code/object that will use them to do that at the right moment.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        D 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          On which OS are you running that code ?

          On a side note, don't call show in the constructor of your widget. It's bad practice. You even call hide directly after the construction which you would not need to do in the first place. Widgets shall not be responsible for showing themselves upon construction, it's the responsibility of the code/object that will use them to do that at the right moment.

          D Offline
          D Offline
          donbfry
          wrote on last edited by
          #3

          @SGaist OS is Windows 11. I'm not sure if you read my explanation of why I did that at the bottom of my code. It was the only way to get the window to pop back up. Otherwise, the window becomes unhidden (while remaining minimized) and the entire application freezes and crashes.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Did you already went through the system tray icon example ?

            It does what you want to do or at least very closely.

            What I would say is missing from your code is a call to QApplication::setQuitOnLastWindowClosed.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            D 2 Replies Last reply
            1
            • SGaistS SGaist

              Did you already went through the system tray icon example ?

              It does what you want to do or at least very closely.

              What I would say is missing from your code is a call to QApplication::setQuitOnLastWindowClosed.

              D Offline
              D Offline
              donbfry
              wrote on last edited by donbfry
              #5

              @SGaist I have not. I apologize but I'm not sure what that has to do with my problem. On run of my application, everything works fine. The window is hidden, the system tray is showing, and everything is running just fine. The problem comes once I try to show the window again and that error happens.

              EDIT: I tried adding app.setQuitOnLastWindowClosed(False) anyways to see if it changed anything but it did not. Once I hit the Ctrl + Alt + T global shortcut the window becomes shown but I still get the error QObject::setParent: Cannot set parent, new parent is in a different thread.

              Here is my updated code:

              import sys
              import ctypes
              import PySide6
              import keyboard
              
              from PySide6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
              from PySide6.QtGui import QIcon, QAction
              from testui import Ui_MainWindow
              
              
              class MainWindow(QMainWindow):
                  def __init__(self):
                      QMainWindow.__init__(self)
              
                      # Setup UI from Qt Designer generated file.
                      self.ui = Ui_MainWindow()
                      self.ui.setupUi(self)
              
                      self.title = "Test Window"
                      self.setWindowTitle(self.title)
              
                      # Initial state of MainWindow.
                      self.is_maximized = False
              
                  def maximize_window(self):
                      if self.is_maximized:
                          return
                      else:
                          self.show()
                          self.is_maximized = True
              
                          user32 = ctypes.WinDLL("user32")
                          hwnd = user32.FindWindowW(None, self.title)
                          user32.ShowWindow(hwnd, 9)
              
              
              if __name__ == "__main__":
                  app = QApplication(sys.argv)
                  app.setQuitOnLastWindowClosed(False)
              
                  window = MainWindow()
              
                  # Hide window after initializing.
                  window.showMinimized()
                  window.hide()
              
                  # System tray.
                  icon = QIcon("tray_icon.ico")
              
                  system_tray = QSystemTrayIcon()
                  system_tray.setIcon(icon)
              
                  tray_menu = QMenu()
              
                  tray_quit = QAction("Quit")
                  tray_quit.triggered.connect(app.quit)
                  tray_menu.addAction(tray_quit)
              
                  system_tray.setContextMenu(tray_menu)
              
                  system_tray.show()
              
                  # Global Shortcuts
                  keyboard.add_hotkey("ctrl+alt+t", lambda: window.maximize_window())
              
                  sys.exit(app.exec())
              

              show() removed from constructor as specified. user32 section under maximize_window() method swapped to after showing the window (seems to work a little more fluid). window.showMinimized() and window.hide() added after window construction. Simply calling only window.hide() or nothing at all causes the application to freeze after using global shortcut to restore window.

              1 Reply Last reply
              0
              • SGaistS SGaist

                Did you already went through the system tray icon example ?

                It does what you want to do or at least very closely.

                What I would say is missing from your code is a call to QApplication::setQuitOnLastWindowClosed.

                D Offline
                D Offline
                donbfry
                wrote on last edited by
                #6

                @SGaist Any ideas?

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  donbfry
                  wrote on last edited by donbfry
                  #7

                  After beating my head against a wall for hours on end trying numerous things, I finally got it to work with no errors. Here is the updated code:

                  import keyboard
                  import ctypes
                  
                  from PySide6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
                  from PySide6.QtGui import QIcon, QAction
                  from testui import Ui_MainWindow
                  
                  
                  class MainWindow(QMainWindow):
                      def __init__(self):
                          QMainWindow.__init__(self)
                  
                          # Setup UI from Qt Designer generated file.
                          self.ui = Ui_MainWindow()
                          self.ui.setupUi(self)
                  
                          self.title = "Test Window"
                          self.setWindowTitle(self.title)
                  
                          # Initial state of MainWindow.
                          self.is_maximized = False
                  
                          # Create QAction with a trigger for restoring window.
                          restore_window = QAction("Restore Window")
                          restore_window.triggered.connect(self.maximize_window)
                  
                          # Global shortcut triggers QAction.
                          keyboard.add_hotkey("ctrl+alt+t", restore_window.trigger)
                  
                      def maximize_window(self):
                          if self.is_maximized:
                              print("Already maximized.")
                              return
                          else:
                              self.show()
                              self.is_maximized = True
                  
                              user32 = ctypes.WinDLL("user32")
                              hwnd = user32.FindWindowW(None, self.title)
                              user32.ShowWindow(hwnd, 9)
                  
                      def closeEvent(self, event):
                          self.is_maximized = False
                          return super().closeEvent(event)
                  
                  
                  if __name__ == "__main__":
                      app = QApplication(sys.argv)
                      app.setQuitOnLastWindowClosed(False)
                  
                      window = MainWindow()
                  
                      # Hide window after initializing.
                      window.show()
                      window.hide()
                  
                      # System tray.
                      icon = QIcon("tray_icon.ico")
                  
                      system_tray = QSystemTrayIcon()
                      system_tray.setIcon(icon)
                  
                      tray_menu = QMenu()
                  
                      tray_quit = QAction("Quit")
                      tray_quit.triggered.connect(app.quit)
                      tray_menu.addAction(tray_quit)
                  
                      system_tray.setContextMenu(tray_menu)
                  
                      system_tray.show()
                  
                      sys.exit(app.exec())
                  

                  I created a QAction with a trigger and on press of the global shortcut, manually triggers the QAction. The trigger shows the window minimized (even those I'm not calling showMinimized() which is interesting). This is where ctypes comes in to bring it to the front.

                  I've attempted to use Slots and Signals to get this to work and it did not so I'm not sure why a QAction trigger.

                  SGaistS 1 Reply Last reply
                  1
                  • D donbfry

                    After beating my head against a wall for hours on end trying numerous things, I finally got it to work with no errors. Here is the updated code:

                    import keyboard
                    import ctypes
                    
                    from PySide6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
                    from PySide6.QtGui import QIcon, QAction
                    from testui import Ui_MainWindow
                    
                    
                    class MainWindow(QMainWindow):
                        def __init__(self):
                            QMainWindow.__init__(self)
                    
                            # Setup UI from Qt Designer generated file.
                            self.ui = Ui_MainWindow()
                            self.ui.setupUi(self)
                    
                            self.title = "Test Window"
                            self.setWindowTitle(self.title)
                    
                            # Initial state of MainWindow.
                            self.is_maximized = False
                    
                            # Create QAction with a trigger for restoring window.
                            restore_window = QAction("Restore Window")
                            restore_window.triggered.connect(self.maximize_window)
                    
                            # Global shortcut triggers QAction.
                            keyboard.add_hotkey("ctrl+alt+t", restore_window.trigger)
                    
                        def maximize_window(self):
                            if self.is_maximized:
                                print("Already maximized.")
                                return
                            else:
                                self.show()
                                self.is_maximized = True
                    
                                user32 = ctypes.WinDLL("user32")
                                hwnd = user32.FindWindowW(None, self.title)
                                user32.ShowWindow(hwnd, 9)
                    
                        def closeEvent(self, event):
                            self.is_maximized = False
                            return super().closeEvent(event)
                    
                    
                    if __name__ == "__main__":
                        app = QApplication(sys.argv)
                        app.setQuitOnLastWindowClosed(False)
                    
                        window = MainWindow()
                    
                        # Hide window after initializing.
                        window.show()
                        window.hide()
                    
                        # System tray.
                        icon = QIcon("tray_icon.ico")
                    
                        system_tray = QSystemTrayIcon()
                        system_tray.setIcon(icon)
                    
                        tray_menu = QMenu()
                    
                        tray_quit = QAction("Quit")
                        tray_quit.triggered.connect(app.quit)
                        tray_menu.addAction(tray_quit)
                    
                        system_tray.setContextMenu(tray_menu)
                    
                        system_tray.show()
                    
                        sys.exit(app.exec())
                    

                    I created a QAction with a trigger and on press of the global shortcut, manually triggers the QAction. The trigger shows the window minimized (even those I'm not calling showMinimized() which is interesting). This is where ctypes comes in to bring it to the front.

                    I've attempted to use Slots and Signals to get this to work and it did not so I'm not sure why a QAction trigger.

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    @donbfry said in Hiding main window on starting, showing later causes "QObject::setParent: Cannot set parent, new parent is in a different thread":

                    
                        # Hide window after initializing.
                        window.showMinimized()
                        window.hide()
                    
                    

                    You do call showMinimized.

                    In any case, glad you found a solution and thanks for sharing it.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    D 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      @donbfry said in Hiding main window on starting, showing later causes "QObject::setParent: Cannot set parent, new parent is in a different thread":

                      
                          # Hide window after initializing.
                          window.showMinimized()
                          window.hide()
                      
                      

                      You do call showMinimized.

                      In any case, glad you found a solution and thanks for sharing it.

                      D Offline
                      D Offline
                      donbfry
                      wrote on last edited by
                      #9

                      @SGaist I was messing around with it before I replied. I pasted in the older one I was experimenting with. I'll update it.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved