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
QtWS25 Last Chance

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 25 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