Python Forum
[PyQt] Need help with class composition / multiple inheritance / polymorphism (?)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] Need help with class composition / multiple inheritance / polymorphism (?)
#1
Question 
Trying to share a class (BodySuperClass), which can be either a QTextEdit or a QPlainTextEdit and contains Qt functions such as focusInEvent;

#!/usr/bin/python3
from PyQt5 import QtWidgets


class Text(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.body = Body()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.body)
        self.setLayout(self.layout)
        self.show()


class BodySuperClass:
    def focusInEvent(self, event):
        print("Hello world")
        super().focusInEvent(event)


class Body(QtWidgets.QPlainTextEdit, BodySuperClass):
    def __init__(self):
        super().__init__()


app = QtWidgets.QApplication([])
widget = Text()
app.exec()
Which fails with;
Quote:Hello world
Traceback (most recent call last):
File "/tmp/pyScript.py", line 18, in focusInEvent
super().focusInEvent(event)
AttributeError: 'super' object has no attribute 'focusInEvent'

Also tried calling super().__init__() from the Body class, but that does not work;

#!/usr/bin/python3
from PyQt5 import QtWidgets


class Text(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.body = Body()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.body)
        self.setLayout(self.layout)
        self.show()


class BodySuperClass:
    def _monkeyInit(self, qTextClass):
        super(qTextClass, self).__init__()

    def focusInEvent(self, event):
        print("Hello world")
        super().focusInEvent(event)


class Body(QtWidgets.QPlainTextEdit, BodySuperClass):
    def __init__(self):
        super().__init__()
        self._monkeyInit(QtWidgets.QPlainTextEdit)


app = QtWidgets.QApplication([])
widget = Text()
app.exec()
Finally, what works is to hardcode inheritance of BodySuperClass to QPlainTextEdit, but I don't like that as when only a QTextEdit object is needed, Body inherits from both;

#!/usr/bin/python3
from PyQt5 import QtWidgets


class Text(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.body = Body()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.body)
        self.setLayout(self.layout)
        self.show()


class BodySuperClass(QtWidgets.QPlainTextEdit):
    def focusInEvent(self, event):
        print("Hello world")
        super().focusInEvent(event)


class Body(QtWidgets.QTextEdit, BodySuperClass):
    def __init__(self):
        super().__init__()
        print("QTextEdit:", isinstance(self, QtWidgets.QTextEdit))
        print("QPlainTextEdit:", isinstance(self, QtWidgets.QPlainTextEdit))


app = QtWidgets.QApplication([])
widget = Text()
app.exec()
Quote:QTextEdit: True
QPlainTextEdit: True
Hello world

What would be the best way to achive this?
Reply
#2
Why QWidget with Layout, why not QMainWindow?

class Text(QtWidgets.QMainWindow):
    def __init__(self):
        super(Text, self).__init__()
        self.body = Body()
        self.setCentralWidget(self.body)
        self.show()
Reply
#3
(May-08-2021, 09:05 PM)Axel_Erfurt Wrote: Why QWidget with Layout, why not QMainWindow?

class Text(QtWidgets.QMainWindow):
    def __init__(self):
        super(Text, self).__init__()
        self.body = Body()
        self.setCentralWidget(self.body)
        self.show()

It is just an example, but since you ask, it is a sticky note application which handle numerous windows simultaneously. As it does not use any of QMainWindow methods, QWidget has less overhead and thus is more appropriated.

https://gitlab.com/william.belanger/qtpa...enix/qtpad
Reply
#4
Found this so far;

#!/usr/bin/python3
from PyQt5 import QtWidgets


class Container(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.plainText = PlainText()
        self.richText = RichText()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.plainText)
        self.layout.addWidget(self.richText)
        self.setLayout(self.layout)
        self.show()


class AbstractText:
    def focusInEvent(self, event):
        print(self.__class__, ":",
              "QTextEdit=", isinstance(self, QtWidgets.QTextEdit),
              " | QPlainTextEdit=", isinstance(self, QtWidgets.QPlainTextEdit))
        self._super.focusInEvent(self, event)  # super().focusInEvent(event)


class PlainText(QtWidgets.QPlainTextEdit, AbstractText):
    _super = QtWidgets.QPlainTextEdit  # Replaces super() in AbstractText methods

    def __init__(self):
        super().__init__()


class RichText(QtWidgets.QTextEdit, AbstractText):
    _super = QtWidgets.QTextEdit  # Replaces super() in AbstractText methods

    def __init__(self):
        super().__init__()


app = QtWidgets.QApplication([])
widget = Container()
app.exec()
Reply
#5
You can use a mixin class.
from PySide2 import QtWidgets
 
class Container(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.plainText = PlainText()
        self.richText = RichText()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.plainText)
        self.layout.addWidget(self.richText)
        self.setLayout(self.layout)
        self.show()
 
class FocusMixin:
    """Insert special focusInEvent to existing widgets"""
    def __init__(self, *args, **kvargs):
        super().__init__(*args, **kvargs)

    def focusInEvent(self, event):
        print(self.__class__, ":",
              "QTextEdit=", isinstance(self, QtWidgets.QTextEdit),
              " | QPlainTextEdit=", isinstance(self, QtWidgets.QPlainTextEdit))
        super().focusInEvent(event)
 
class PlainText(FocusMixin, QtWidgets.QPlainTextEdit):
    """PlainText with focus mixin"""

class RichText(FocusMixin, QtWidgets.QTextEdit):
    """RichText with focus mixin"""

app = QtWidgets.QApplication([])
widget = Container()
app.exec_()
Alfalfa likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] Program with Multiple Windows - how to use Class: Riddle 1 2,971 Apr-09-2020, 08:30 PM
Last Post: Riddle

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020