3

I have an extremely strange behaviour of a QPainter. In my 'MainWindow::paintEvent()' it works correctly:

QPainter painter(this);
qDebug() << "painter adress in paintEvent: " << (&painter);
painter.setBrush(Qt::red);
painter.drawRect(100, 100, 100, 100);

So far, so good. But I actually want to paint using a function of a class I wrote, so my 'paintEvent()' looks like this:

QPainter painter(this);
qDebug() << "painter adress in paintEvent: " << (&painter);
painter.setBrush(Qt::red);
painter.drawRect(100, 100, 100, 100);
instance_of_my_class->paint(&painter);
painter.drawRect(150, 150, 100, 100);

And the 'paint(QPainter *painter)', which is called above, looks like this:

qDebug() << "painter adress in paint: " << painter;
painter->setBrush(QColor(0, 0, 80));
painter->drawRect(0, 0, 1000, 1000);

Obviously, I would now expect to see a dark blue background with one red rectangle (the second one, the first one should be overpainted within 'paint'). However, I see the two red rectangles and in my toolbar all icons have a dark blue background. Furthermore, the output of 'qDebug()' looks as follows:

painter adress in paintEvent:  0xbfd43b54
painter adress in paint:  0xbfd43b54

It definetly is the same QPainter, but within my class it is painting below the icons in my toolbar!?!

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Bianfable
  • 237
  • 5
  • 13

1 Answers1

3

It's generally an error to paint anything in a QMainWindow paint event. A main window can have various child widgets. Your painter will gladly interfere with those - you don't show any code that enumerates dock windows and child windows, etc.

To paint something in a main window, you need to paint it in a separate widget, and that widget has to be given via setCentralWidget to the main window.

You absolutely don't need to use a QMainWindow if you don't need its full functionality. That means: if you don't care about the menu bar and the dock widgets, don't use QMainWindow.

This works:

screenshot

#include <QApplication>
#include <QMainWindow>
#include <QPainter>

class Bottom {
public:
    void paint(QPainter * p) {
        p->setBrush(Qt::blue);
        p->drawRect(0, 0, 1000, 1000);
    }
};

class Top : public QWidget {
    Bottom * m_bottom;
    void paintEvent(QPaintEvent *) {
        QPainter p(this);
        p.setPen(Qt::NoPen);
        p.setBrush(Qt::red);
        p.drawRect(0, 0, 100, 100);
        m_bottom->paint(&p);
        p.setBrush(Qt::green);
        p.drawRect(50, 50, 100, 100);
    }
public:
    Top(Bottom * bottom, QWidget * parent = 0) :
        QWidget(parent), m_bottom(bottom) {}
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    Bottom b;
    Top t(&b);
    w.setCentralWidget(&t);
    w.setMinimumSize(200, 200);
    w.show();
    return a.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thanks for your advice, but unfortunately it did not solve my problem. I wrote a new class inheriting from QWidget, set an instance of it as central widget on my MainWindow and moved the paint stuff in the paintEvent() of the widget. But still: only the paint commands in the paintEvent() are executed, the paint in my sub class is ignored (now it doesn't paint over the toolbar any more). – Bianfable Mar 15 '14 at 15:46
  • @Bianfable You're not showing any code and this is counterproductive. You must have a complete, single file, minimum example that shows what you're doing. Why is it important? Because I can post a test case right here that shows that it works and all I do is follow my own instructions. Your problem is in what you're not showing. There are hundreds if not thousands of questions like yours here: people who insist in not showing self-contained, minimal code, and every time I post a counterexample they say something like "ooh, it was in some other code of mine". Duh. Show your code. – Kuba hasn't forgotten Monica Mar 15 '14 at 16:02
  • 1
    Your example was simplest to build upon. Thank you! – kuzavas Jun 22 '17 at 13:10