如何在子部件而不是父部件上画一条线?
How to draw a line on a child widget instead of the parent widget?
我正在尝试在 QWidget 上画一条线(和一些其他图元)。该 QWidget 实际上是 "on top of" 另一个带有图片的小部件。我想在图片上画线和圆圈。
我已经会画线了。我可以用这段代码做到这一点:
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);
,它会绘制一些东西,但它不在子控件上,而是在父控件上。
关于这个主题的文档非常清楚:
Each widget performs all painting operations from within its
paintEvent() function. This is called whenever the widget needs to be
redrawn, either as a result of some external change or when requested
by the application.
您应该只在其绘制事件中绘制一个小部件,并且您应该只在那个特定的小部件上绘制。
The problem is the line that reads QPainter painter(drawnElements);
当然可以。您需要改为观看 target 小部件并捕获其绘制事件。要控制绘图的顺序,您也应该显式地将事件传递给目标。
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);
}
您也可以考虑使用 overlay widget。
我正在尝试在 QWidget 上画一条线(和一些其他图元)。该 QWidget 实际上是 "on top of" 另一个带有图片的小部件。我想在图片上画线和圆圈。
我已经会画线了。我可以用这段代码做到这一点:
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);
,它会绘制一些东西,但它不在子控件上,而是在父控件上。
关于这个主题的文档非常清楚:
Each widget performs all painting operations from within its paintEvent() function. This is called whenever the widget needs to be redrawn, either as a result of some external change or when requested by the application.
您应该只在其绘制事件中绘制一个小部件,并且您应该只在那个特定的小部件上绘制。
The problem is the line that reads
QPainter painter(drawnElements);
当然可以。您需要改为观看 target 小部件并捕获其绘制事件。要控制绘图的顺序,您也应该显式地将事件传递给目标。
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);
}
您也可以考虑使用 overlay widget。