如何在子小部件而不是父窗口小部件上绘制一条线

How to draw a line on a child widget instead of the parent widget?

本文关键字:小部 窗口 绘制 一条      更新时间:2023-10-16

我正在尝试在qwidget上绘制一条线(和其他一些原语)。Qwidget实际上是在另一个带有图片的小部件的基础上。我想在图片上画线和圆圈。

我知道如何绘制线路。我可以使用此代码做到这一点:

bool MySpecialWidget::eventFilter( QObject* watched, QEvent* event )
{
    if (watched == this && event->type() == QEvent::Paint)
    {
        QPainter painter(this);
        painter.translate(50, 50);
        painter.setPen(QPen(Qt::blue, 12));
        painter.setBrush(Qt::BrushStyle::SolidPattern);
        painter.drawLine(0, 0, 200, 200);
    }
    return false;
}

,但是我真正想做的是将小部件放置以保持图片,然后将小部件放在其上以保持线路。这样:

MySpecialWidget::MySpecialWidget(QWidget *parent) : QWidget(parent)
{
    QRect position = QRect(30, 50, 600, 600);
    pictureBox = new QLabel(parent);
    pictureBox->setGeometry(position);
    pictureBox->setPixmap(QPixmap(QString::fromUtf8(":/main/graphics/MyPicture.png")));
    pictureBox->setScaledContents(true);
    drawnElements = new QWidget(parent);
    drawnElements->setGeometry(position);
    drawnElements->raise();
    this->installEventFilter(this);
}

然后绘制线条和原语,我想这样做:

bool MySpecialWidget::eventFilter( QObject* watched, QEvent* event )
{
    if (watched == this && event->type() == QEvent::Paint)
    {
        QPainter painter(drawnElements);
        painter.translate(50, 50);
        painter.setPen(QPen(Qt::blue, 12));
        painter.setBrush(Qt::BrushStyle::SolidPattern);
        painter.drawLine(0, 0, 200, 200);
    }
    return false;
}

但这不起作用。什么都没有画。空白。

问题是读取QPainter painter(drawnElements);

的行

如果我说 QPainter painter(this);,它会绘制某些内容,但它不在子小部件上,而是在父母的小部件上。

该文档在该主题上很清楚:

每个小部件都从其内部执行所有绘画操作 PaintEvent()函数。每当小部件需要是 重新绘制,无论是由于某些外部变更而导致的 通过应用程序。

您应该只在其油漆事件中绘制小部件,而您只能在该特定的小部件上绘制。

问题是读取QPainter painter(drawnElements);

的行

当然。您需要观看目标小部件,然后捕获其油漆事件。要控制绘图顺序,您也应该明确将事件交付给目标。

bool MySpecialWidget::eventFilter( QObject* watched, QEvent* event )
{
    //         *** vvvvvvvvvvvvv *** (A)
    if (watched == drawnElements && event->type() == QEvent::Paint)
    {
        // Let the target draw itself first.
        watched->event(event);
        // Then overlay our content on it.
        //           *** vvvvvvvvvvvvv *** (B) - must match (A)!
        QPainter painter(drawnElements);
        painter.translate(50, 50);
        painter.setPen(QPen(Qt::blue, 12));
        painter.setBrush(Qt::BrushStyle::SolidPattern);
        painter.drawLine(0, 0, 200, 200);
        return true; // The event is already handled.
    }
    return false;
}
MySpecialWidget::MySpecialWidget(QWidget *parent) : QWidget(parent)
{
    //...
    drawnElements->installEventFilter(this);
}

可以随意考虑使用覆盖小部件。