Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. singleton in python, with qobject

singleton in python, with qobject

Scheduled Pinned Locked Moved Solved Language Bindings
3 Posts 3 Posters 4.4k 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.
  • U Offline
    U Offline
    user4592357
    wrote on 8 Mar 2018, 17:00 last edited by
    #1

    i need a singleton class, so here's what i got:

    __instances = {}
    
    
    class _Singleton(type):
        def __new__(meta, name, bases, members):
            for class_ in bases:
                if class_ is not Singleton and issubclass(class_, Singleton):
                    raise TypeError(("Invalid base type (as subclass of Singleton):", class_))
            return type.__new__(meta, name, bases, members)    
    
        def __call__(class_, *args, **kwargs):
            if class_ is Singleton:
                raise TypeError("The base Singleton type cannot be instantiated")
            if class_ not in __instances:
                __instances[class_] = super(_Singleton, class_).__call__(*args, **kwargs)
            return __instances[class_]
    
    Singleton = type('_', (), {}) # dummy type to allow base type creation
    Singleton = _Singleton('Singleton', (object, ), {})
    

    my controller object is a subclass of QObject, and i get an error:

    class Controller(QObject, '''metaclass='''Singleton):
    TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
    
    1 Reply Last reply
    0
    • J Offline
      J Offline
      jazzycamel
      wrote on 9 Mar 2018, 12:33 last edited by
      #2

      The following is my implementation (and a usage example) of a singleton I use regularly:

      try: from PyQt5.QtCore import pyqtWrapperType
      except ImportError:
          from sip import wrappertype as pyqtWrapperType
      
      class Singleton(pyqtWrapperType, type):
          def __init__(cls, name, bases, dict):
              super().__init__(name, bases, dict)
              cls.instance=None
      
          def __call__(cls,*args,**kw):
              if cls.instance is None:
                  cls.instance=super().__call__(*args, **kw)
              return cls.instance
      
      if __name__=="__main__":
          from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty
      
          class MyObject(QObject, metaclass=Singleton):
              def __init__(self, parent=None, **kwargs):
                  super().__init__(parent, **kwargs)
      
                  self._x=0
      
              def x(self): return self._x
      
              @pyqtSlot(int)
              def setX(self, x): self._x=x
      
              x=pyqtProperty(int, x, setX)
      
          print(MyObject().x)
          MyObject().x=1
          print(MyObject().x)
      

      I've actually shared this example/technique so many times now that I just quickly created a git repo (https://github.com/jazzycamel/PyQt5Singleton) and a PyPi package (https://pypi.python.org/pypi/PyQt5Singleton) so you can just install it via pip:

      $ pip install PyQt5Singleton
      

      and use it (as above):

      from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty
      from PyQt5Singleton import Singleton
      
      class MyObject(QObject, metaclass=Singleton):
          def __init__(self, parent=None, **kwargs):
              super().__init__(parent, **kwargs)
      
              self._x=0
      
          def x(self): return self._x
      
          @pyqtSlot(int)
          def setX(self, x): self._x=x
      
          x=pyqtProperty(int, x, setX)
      
      if __name__=="__main__":
          print(MyObject().x)
          MyObject().x=1
          print(MyObject().x)
      

      Hope this helps :)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      4
      • P Offline
        P Offline
        pk13055
        wrote on 6 Mar 2025, 12:24 last edited by pk13055 20 days from now
        #3

        @jazzycamel Although your post is almost 7 years old at this point, it still works flawlessly. I created an account just to thank you for this haha :D (PS - For others stumbling upon this, here's a simple implementation for PyQt6)

        import collections
        
        from PyQt6.QtCore import QObject
        
        
        class Singleton(type(QObject)):
            def __init__(cls, name, bases, dict):
                super().__init__(name, bases, dict)
                cls.instance = None
        
            def __call__(cls, *args, **kw):
                if cls.instance is None:
                    cls.instance = super().__call__(*args, **kw)
                return cls.instance
        
        
        class WindowManager(QObject, metaclass=Singleton):
        
            def __init__(self, parent=None, **kwargs) -> None:
        
                # Always call the parent class's __init__ first
                super().__init__(parent, **kwargs)
        
                # Window configuration
                self.window_width = 550  # Fixed width for equation windows
                self.window_height = 250  # Fixed height for equation windows
                self.window_margin = 20  # Margin from screen edge
                self.vertical_gap = 20  # Gap between windows
        
                # Calculate max windows that fit on screen
                self.max_windows = 3
        
                # Use deque with dynamic maxlen to auto-remove old windows
                self.active_windows = collections.deque(maxlen=self.max_windows)
                self.window_positions = []  # Track positions of windows
        
        window_manager = WindowManager()
        
        
        1 Reply Last reply
        1

        • Login

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