1

I'm learning to use PyQt5 and have run across a problem. My code is attempting to just draw a simple black box in the QMainWindow object by writing a second class PaintWidget which inherits from QWidget. I've posted my code first, and the correct one below it.

class PaintWidget(QWidget):

    def __init__(self):
        super().__init__()
        self.qp = QPainter()
        self.initUI()

    def initUI(self):
        self.qp.fillRect(1,1,100,100, Qt.black)

Correct:

class PaintWidget(QWidget):
    def paintEvent(self, event):
        qp = QPainter(self)
        qp.fillRect(1, 1, 100, 100, Qt.black)

This is what confuses me. In order to create this class, we need to inherint from the super class QWidget, inorder to do so we use the function super().__init__() under __init__(self). We then set up the QPaint object which we will use in our method initUI() which actually does the work. Now this doesn't work when I run it.

The second, correct class, doesn't even seem to inherent, since it has no super().__init__(), even worse, it is setting up a method that is never even called (paintevent(self, event)), which takes an argument that seemingly comes from nowhere. Can someone point out why I'm wrong?

3
  • paintEvent is called by PyQt5 with an argument it provides, and if you don’t override __init__, it defaults to the parent class’s, put simply. Commented May 24, 2017 at 7:31
  • So setting up a new __init__ is not needed? The reason I wanted to make one is that I thought it would make passing extra parameters to it easier, such as if I waned to change to color of the rectangle, it'd be easier to call painter = PaintWidget(Qt.yellow). Commented May 24, 2017 at 7:36
  • 1
    @Astrum, no __init__ is only needed if you want to initialize anything in it. Otherwise, the runtime will simply call the parent (super().__init__()) directly. However, if you want constructor parameters, go ahead and add it. It is not a problem either way. The difference is where you call the painter. Commented May 24, 2017 at 7:39

1 Answer 1

2

There is absolutely no difference to inheritance between the two cases. In both cases you say class PaintWidget(QWidget), so you are inheriting the QWidget.

The difference is in where you draw. In constructor (__init__), the widget is not yet mapped to the screen, so if you try to draw there, it won't have effect.

When the widget is actually displayed on screen, the system will invoke the paintEvent, which is a virtual method of the QWidget, and that is where you must draw the content. You only define that method in the second example.

Note that you need fresh QPainter in each invocation of the paintEvent. Creating one in the constructor and then using it in paintEvent would not work.

Also, most windowing systems don't remember the content of the widget when it is not actually visible on screen and rely on being able to call the paintEvent whenever the widget becomes visible again. So the method will likely be called many times. In contrast, the constructor, __init__, is only called once when creating the object.

Sign up to request clarification or add additional context in comments.

4 Comments

So that kind of makes sense. I still have a question. Why do we have to call this class by doing self.painter = PaintWidget(self)? Usually when I've had to call classes, the self is left out.
@Astrum, QWidget wants the parent widget as argument. Which also means the __init__ should actually be def __init__(self, parent): super().__init__(parent) … (plus any other parameters you want your class.
Ok, so this may be offtopic, but why is it different from the usual classes? This is the first time I've come across this type of thing before and it seems odd. If the class has already inherited the parent, it seems odd to have to be explicit about it.
@Astrum, this is not different from other classes. The parent does not mean the class it inherits—that is a “base”. The parent is the widget on which your widget will appear on screen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.