Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt: Using QPainter on child widgets

I'm having a Qt/C++ problem with a simple QWidget program that draws an ellipse inside a child QWidget.

The program is composed of:
(1) A parent QWidget
(2) A child QWidget (used as the drawing surface for an ellipse)
(3) A draw QPushButton

Here is part of the code (QPushButton Slot and Signal code omitted for simplicity)

void Draw::paintEvent(QPaintEvent *event) {
    QPainter painter;
    painter.begin(child_Widget);    //The line with the problem
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
    painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
    painter.drawEllipse(50, 50, 100, 100);
    painter.end();}

Line 2 painter.begin(child_Widget); doesn't do anything. The program draws the ellipse only if I replace line 2 with painter.begin(this); but that draws on the parent QWidget and not on the child QWidget as desired.

P.S. I have the child_Widget housed inside a GroupBox which in turn is housed inside a QVBoxLayout.

Any Suggestion?

Thanks.

like image 356
Ben E Avatar asked Oct 30 '09 00:10

Ben E


3 Answers

First thing I'd try would be to install an event filter on the child widget (see QObject::installeEventFilter()), then, in the parent widget, grap the QEvent::Paint event, and do the painting there.

Where you create the child widget :

// ...
    childWidget = new QWidget(this);
    childWidget->installEventFilter(this);
// ...

Then in the parent :

bool Draw::eventFilter(QObject* watched, QEvent* event)
{
    if (watched == childWidget && event->type() == QEvent::Paint) {
        QPainter painter;
        painter.begin(childWidget);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
        painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
        painter.drawEllipse(50, 50, 100, 100);
        painter.end();
        return true; // return true if you do not want to have the child widget paint on its own afterwards, otherwise, return false.
    }
    return false;
}
like image 132
Fred Avatar answered Nov 14 '22 19:11

Fred


As stated in the QPainter documentation

Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent widget attribute is set. On Mac OS X and Windows, you can only paint in a paintEvent() function regardless of this attribute's setting.

If you want to draw on that widget you will need to do so from it's own paintEvent().

like image 4
linuxman Avatar answered Nov 14 '22 20:11

linuxman


You could paint on a pixmap and draw the pixmap in the widget paint event. And it can be any function or slot, not necessarily a paint event, e.g. you can have multiple for drawing different objects. You can draw from anywhere on a pixmap, the requirement that the paint event is used is just for the widget that will draw the pixmap. You can even draw in another thread if it is a complex scene and only update the result from the pixmap in the main thread.

like image 1
dtech Avatar answered Nov 14 '22 19:11

dtech