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. I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly? TrayIcon().show()
Forum Updated to NodeBB v4.3 + New Features

I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly? TrayIcon().show()

Scheduled Pinned Locked Moved Solved Qt for Python
12 Posts 4 Posters 1.1k Views 2 Watching
  • 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.
  • I Offline
    I Offline
    ideaplus
    wrote on last edited by
    #1

    I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly after init TrayIcon? TrayIcon().show()

    # It works:
    # my_tray_icon = TrayIcon(my_widget)
    # my_tray_icon.show()
    
    # But why doesn't this work? The icon does not appear in the system tray.
    TrayIcon(my_widget).show()
    
    import sys
    
    from PySide2.QtGui import QIcon
    from PySide2.QtWidgets import QSystemTrayIcon, QAction, QMenu, QApplication, QWidget, qApp
    
    
    class TrayIcon(QSystemTrayIcon):
        def __init__(self, app):
            super().__init__()
            self.app = app
            self.setIcon(QIcon('icon.png'))
            self.activated.connect(self.icon_activated)
            self.tray_menu = QMenu(QApplication.desktop())
            self.show_action = QAction('&show')
            self.quit_action = QAction('&exit')
            self.show_action.triggered.connect(app.show)
            self.quit_action.triggered.connect(qApp.quit)
            self.tray_menu.addAction(self.show_action)
            self.tray_menu.addAction(self.quit_action)
            self.setContextMenu(self.tray_menu)
    
        def icon_activated(self, reason):
            if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
                self.app.show()
                # for Windows
                self.app.activateWindow()
                # for macOS
                self.app.raise_()
    
    
    def main():
        app = QApplication(sys.argv)
        app.setQuitOnLastWindowClosed(False)
        my_widget = QWidget()
    
        # It works:
        # my_tray_icon = TrayIcon(my_widget)
        # my_tray_icon.show()
    
        # But why doesn't this work?
        TrayIcon(my_widget).show()
    
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()
    
    JonBJ 1 Reply Last reply
    0
    • I ideaplus

      I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly after init TrayIcon? TrayIcon().show()

      # It works:
      # my_tray_icon = TrayIcon(my_widget)
      # my_tray_icon.show()
      
      # But why doesn't this work? The icon does not appear in the system tray.
      TrayIcon(my_widget).show()
      
      import sys
      
      from PySide2.QtGui import QIcon
      from PySide2.QtWidgets import QSystemTrayIcon, QAction, QMenu, QApplication, QWidget, qApp
      
      
      class TrayIcon(QSystemTrayIcon):
          def __init__(self, app):
              super().__init__()
              self.app = app
              self.setIcon(QIcon('icon.png'))
              self.activated.connect(self.icon_activated)
              self.tray_menu = QMenu(QApplication.desktop())
              self.show_action = QAction('&show')
              self.quit_action = QAction('&exit')
              self.show_action.triggered.connect(app.show)
              self.quit_action.triggered.connect(qApp.quit)
              self.tray_menu.addAction(self.show_action)
              self.tray_menu.addAction(self.quit_action)
              self.setContextMenu(self.tray_menu)
      
          def icon_activated(self, reason):
              if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
                  self.app.show()
                  # for Windows
                  self.app.activateWindow()
                  # for macOS
                  self.app.raise_()
      
      
      def main():
          app = QApplication(sys.argv)
          app.setQuitOnLastWindowClosed(False)
          my_widget = QWidget()
      
          # It works:
          # my_tray_icon = TrayIcon(my_widget)
          # my_tray_icon.show()
      
          # But why doesn't this work?
          TrayIcon(my_widget).show()
      
          sys.exit(app.exec_())
      
      
      if __name__ == '__main__':
          main()
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @ideaplus said in I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly? TrayIcon().show():

      But why doesn't this work? The icon does not appear in the system tray.

      TrayIcon(my_widget).show()

      Because you are not holding a Python reference on the resulting TrayIcon. So Python releases the reference immediately. I'm not sure, but you might find the following behaves similarly (losing the icon):

          my_tray_icon = TrayIcon(my_widget)
          my_tray_icon.show()
          my_tray_icon = None
      
      1 Reply Last reply
      0
      • I Offline
        I Offline
        ideaplus
        wrote on last edited by ideaplus
        #3

        @JonB
        Maybe this is a feature of pyqt. Thanks for your reply.

        from PySide2.QtWidgets import QErrorMessage, QApplication
        
        app = QApplication([])
        
        error_dialog = QErrorMessage()
        error_dialog.showMessage('Oh no!')
        
        QErrorMessage().showMessage('Oh no!')
        
        app.exec_()
        
        class Test:
            def __init__(self):
                self.x = 1
        
            def print(self):
                print(self.x)
        
        
        Test().print()
        
        1 Reply Last reply
        0
        • I Offline
          I Offline
          ideaplus
          wrote on last edited by
          #4
          from PySide2.QtWidgets import QApplication, QMessageBox
          
          app = QApplication([])
          
          QMessageBox().critical(None, 'Error', "A Error A Error A Error", buttons=QMessageBox.Ok)
          
          app.exec_()
          
          
          JonBJ 1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            Can you show the exact code you are using with your custom tray icon class ?

            @JonB is more than likely correct with the object getting garbage collected.

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

            1 Reply Last reply
            0
            • I ideaplus
              from PySide2.QtWidgets import QApplication, QMessageBox
              
              app = QApplication([])
              
              QMessageBox().critical(None, 'Error', "A Error A Error A Error", buttons=QMessageBox.Ok)
              
              app.exec_()
              
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #6

              @ideaplus
              Not sure what you are proving with your QMessageBox() example, the original was QSystemTrayIcon, QMessageBox() may work differently. In any case, your QErrorMessage() example is assigned to a variable whose scope persists, and your QMessageBox().critical() blocks until the user dismisses it, so in both cases they will not be collected to stop it working, and I would expect to work under PyQt as well as PySide2.

              I can't comment on PySide2 behaviour, may differ from PyQt in this respect. I do know that in PyQt I came a similar cropper when I created a modeless QDialog which had no parent (i.e. application-modeless). I found that if I did not keep a global reference to the modeless dialog --- even though I never actually used it anywhere --- then I simply would not get to see it, as it was being deleted/garbage collected immediately after creation!

              1 Reply Last reply
              0
              • JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @Denni-0
                @ideaplus is asking why the following works:

                    # It works:
                    my_tray_icon = TrayIcon(my_widget)
                    my_tray_icon.show()
                

                while the following does not:

                    # But why doesn't this work?
                    TrayIcon(my_widget).show()
                

                That's all he's asking.

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

                  And as @JonB answered, in the second version, there's nothing holding any reference to the underlying object hence it gets garbage collected and destroyed before being even shown.

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

                  1 Reply Last reply
                  0
                  • JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @Denni-0 said in I write a class TrayIcon inherit QSystemTrayIcon, why I can't call show() directly? TrayIcon().show():

                    And actually in neither of them is the code actually holding onto a reference to the underlying objects as self. is not used in either case

                    That's not how referencing works in Python, or at least not as it applies to this case.

                    def main():
                        # It works:
                        my_tray_icon = TrayIcon(my_widget)
                        my_tray_icon.show()
                    
                        sys.exit(app.exec_())
                    

                    my_tray_icon is only a local variable to a function, so nothing to do with self. However, its scope extends to the end of the function. Even though it is not referenced again after the .show(), its reference persists until the function exits, and will not be garbage collected until then. Since it is still in scope across the app.exec_(), that is why it works.

                    1 Reply Last reply
                    1
                    • JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @Denni-0
                      Thanks for your comment.

                      I just wanted the OP to know that what you wrote about "in neither of them is the code actually holding onto a reference to the underlying objects as self. is not used in either case" is incorrect, in case he cares even if you do not.

                      I take your comments about the lack of clarity/confusion in my posts compared to yours, and will try to learn.

                      All the best for New Year :)

                      1 Reply Last reply
                      0
                      • JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by
                        #11

                        @Denni-0
                        I persist because you persist :)
                        Let's move on now, as I said I wish you all the best for 2020!

                        1 Reply Last reply
                        0
                        • JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @Denni-0
                          It would probably depend on how much I couldn't live with what you posted, but on this occasion/thread I will try to be good and just say nothing ;-)

                          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