Python Forum
Python C++ Template Equivalent - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Python C++ Template Equivalent (/thread-33539.html)



Python C++ Template Equivalent - deanhystad - May-03-2021

I have the following code that adds a couple of features to QWidget and QGroupBox.
class View(QtWidgets.QWidget):
    """Add upload and update loop to QWidget"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.update_list = UpdateList(1.0)

    def showEvent(self, event):
        """Start update loop when window is shown"""
        self.upload()
        self.update_list.start()
        event.accept()

    def closeEvent(self, event):
        """Stop update loop when window is closed"""
        self.update_list.stop()
        event.accept()

    def upload(self):
        """Forward update message to all ValueControl objects"""
        if self.isVisible():
            for child in self.children():
                if isinstance(child, ValueControl):
                    child.update_value()


class GroupView(QtWidgets.QGroupBox):
    """Add upload and update loop to QBoxGroup"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.update_list = UpdateList(1.0)

    def showEvent(self, event):
        """Start update loop when window is shown"""
        self.upload()
        self.update_list.start()
        event.accept()

    def closeEvent(self, event):
        """Stop update loop when window is closed"""
        self.update_list.stop()
        event.accept()

    def upload(self):
        """Forward update message to all ValueControl objects"""
        if self.isVisible():
            for child in self.children():
                if isinstance(child, ValueControl):
                    child.update_value()
The code is identical except for the superclass. I would like to make a superclass that implements the common behavior, but openEvent(), closeEvent() and self.children() are all part of the new behavior and these methods are inherited from QWidget.

In C++ I would make a template. How would you do this in Python?


RE: Python C++ Template Equivalent - Gribouillis - May-03-2021

You could perhaps write a Mixin class implementing the three methods.


RE: Python C++ Template Equivalent - deanhystad - May-03-2021

I tried a mixin. It works, but the mixin provides only half the additional functionality because it really needs to act like a QWidget to get the show/close events.
class BaseView():
    """Abstract base class for views"""
    def __init__(self):
       self.update_list = UpdateList(1.0)

    def upload(self):
        """Forward update message to all ValueControl objects"""
        if self.isVisible():
            for child in self.children():
                if isinstance(child, ValueControl):
                    child.update_value()


class View(QtWidgets.QWidget, BaseView):
    """Add upload and update loop to QWidget"""

    def __init__(self, *args, **kwargs):
        QtWidgets.QWidget.__init__(self, *args, **kwargs)
        BaseView.__init__(self)

    def showEvent(self, event):
        """Start update loop when window is shown"""
        self.upload()
        self.update_list.start()
        event.accept()

    def closeEvent(self, event):
        """Stop update loop when window is closed"""
        self.update_list.stop()
        event.accept()
A benefit of this approach is giving View and GroupView a common superclass makes them easier to find using methods like QtWidget.findChildren(BaseView).


RE: Python C++ Template Equivalent - Gribouillis - May-03-2021

Why dont you write showEvent() and closeEvent() in the BaseView class ? You could also call it ViewMixin to clarify its role. Also there are arguments for writing the Mixin classes before the normal parent classes in the sequence of base classes.


RE: Python C++ Template Equivalent - deanhystad - May-03-2021

I would swear that I tried this before and it threw up all over me. Now it works fine.
class BaseView():
    """Abstract base class for views"""
    def __init__(self):
       self.update_list = UpdateList(1.0)

    def showEvent(self, event):
        """Start update loop when window is shown"""
        self.upload()
        self.update_list.start()
        event.accept()

    def closeEvent(self, event):
        """Stop update loop when window is closed"""
        self.update_list.stop()
        event.accept()

    def upload(self):
        """Forward update message to all ValueControl objects"""
        if self.isVisible():
            for child in self.children():
                if isinstance(child, ValueControl):
                    child.update_value()


class View(QtWidgets.QWidget, BaseView):
    """Add upload and update loop to QWidget"""

    def __init__(self, *args, **kwargs):
        BaseView.__init__(self)
        QtWidgets.QWidget.__init__(self, *args, **kwargs)



RE: Python C++ Template Equivalent - deanhystad - May-04-2021

Actually it doesn't work fine. Moving showEvent() and closeEvent() to the mixin class results in not capturing these events.


RE: Python C++ Template Equivalent - Gribouillis - May-04-2021

The problem is that I know almost nothing in PyQt5. Do you have the same issue if you write BaseView before QWidget in the list of base classes of View ?

You could also try something like

class View...
    closeEvent = BaseView.closeEvent



RE: Python C++ Template Equivalent - deanhystad - May-04-2021

This discussion has been very educational. Thanks!

This works.
class BaseView():
    """Abstract base class for views"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.update_list = UpdateList(1.0)

    def showEvent(self, event):
        """Start update loop when window is shown"""
        self.upload()
        self.update_list.start()
        event.accept()

    def closeEvent(self, event):
        """Stop update loop when window is closed"""
        self.update_list.stop()
        event.accept()

    def upload(self):
        """Forward update message to all ValueControl objects"""
        print(self)
        if self.isVisible():
            for child in self.children():
                if isinstance(child, ValueControl):
                    child.update_value()

class View(BaseView, QtWidgets.QWidget):
    """Add upload and update loop to QWidget"""

class GroupView(BaseView, QtWidgets.QGroupBox):
    """Add upload and update loop to QBoxGroup"""