Qt:在子部件上使用QPainter

5
我正在处理一个关于Qt/C++的问题,这个问题与一个简单的 QWidget 程序有关,该程序在子 QWidget 中绘制一个椭圆。
程序由以下组成: (1) 一个父 QWidget (2) 一个子 QWidget(用作绘制椭圆的绘图表面) (3) 一个绘制 QPushButton
以下是部分代码(为了简便省略了 QPushButton Slot 和 Signal 代码)。
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();}

第二行的painter.begin(child_Widget);没有起到任何作用。只有当我将第二行替换为painter.begin(this);时,程序才会绘制椭圆,但这会在父QWidget上绘制而不是所需的子QWidget

P.S. 我将child_Widget放置在一个GroupBox中,GroupBox又放置在一个QVBoxLayout中。

有什么建议吗?

谢谢。

3个回答

8

首先,我会尝试在子窗口上安装事件过滤器(请参见QObject::installEventFilter()),然后在父窗口中获取QEvent::Paint事件并在那里进行绘制。

在创建子窗口时:

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

然后在父窗口中:

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; // 如果您不希望子窗口之后自行绘制,请返回true,否则返回false。
    }
    return false;
}

4
QPainter文档中所述:
警告:当绘图设备是部件时,只能在paintEvent()函数内或由paintEvent()调用的函数中使用QPainter;除非设置了Qt::WA_PaintOutsidePaintEvent部件属性。在Mac OS X和Windows上,无论此属性的设置如何,都只能在paintEvent()函数中绘制。
如果要在该部件上绘制,则需要从其自己的paintEvent()中进行。

Linuxman,我该怎样做?我最初在子小部件中设置了一个渲染区域,作为父小部件类内实例化的组件,但最终将两个合并成一个类,因为我需要让渲染区域访问父小部件类的成员,而使用friend关键字不起作用。此外,除了QWidget之外,是否还有其他设备可以绘制椭圆而不使用QPainter? - Ben E
2
通过子类化并重新实现它的paintEvent()函数。 - linuxman

1
你可以在一个 pixmap 上绘制图像,然后在小部件的 paint 事件中绘制该 pixmap。它可以是任何函数或插槽,不一定是 paint 事件,例如,您可以为绘制不同对象而有多个插槽。您可以从 pixmap 上的任何位置绘制,只要绘制 pixmap 的小部件使用 paint 事件即可。如果场景很复杂,甚至可以在另一个线程中绘制,然后仅在主线程中更新 pixmap 的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接