Qt绘图之QWidget | 您所在的位置:网站首页 › qt截图子widget › Qt绘图之QWidget |
一、概述
我们知道当一个QWidget以另外一个QWidget作为父对象时,显示父对象会自动显示子对象,今天就对其实现过程做个简单分析。 二、测试源码 subwidget.h #ifndef SUBWIDGET_H #define SUBWIDGET_H #include #include #include #include #include class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = nullptr); void paintEvent(QPaintEvent* event); QSize sizeHint() const { return QSize(400, 400); } void moveEvent(QMoveEvent *event) { qDebug() } void SubWidget::paintEvent(QPaintEvent* event) { QPainter painter(this); QPen pen; pen.setColor(Qt::blue); painter.setPen(pen); painter.drawText(10, 100, "This is subWidget"); } widget.h #ifndef WIDGET_H #define WIDGET_H #include #include #include class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); void paintEvent(QPaintEvent* event); QSize sizeHint() const { return QSize(400, 400); } }; #endif // WIDGET_H widget.cpp #include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { } Widget::~Widget() { } void Widget::paintEvent(QPaintEvent* event) { QPainter painter(this); painter.drawText(50, 50, "This is widget"); } main.cpp #include "widget.h" #include "subwidget.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; SubWidget subWidget(&w); w.show(); return a.exec(); } 三、分析父对象绘制同时其对象也会绘制情景SubWidget 是Widget 的子对象,Widget 绘制的时候会同时绘制SubWidget ,以下是其调用堆栈: w.show() ==> QWidget::setVisible ==> QLayout::activate> ==> QLayoutPrivate::doResize ==> QBoxLayout::setGeometry ==> QWidgetItem::setGeometry ==> QWidget::setGeometry 第二次根据父对象空间调整子对象的layoutw.show() ==> QWidget::setVisible ==> QWidgetPrivate::show_helper> ==> QWidgetPrivate::sendPendingMoveAndResizeEvents ==> QCoreApplication::sendEvent ==> QApplicationPrivate::notify_helper ==> QLayout::widgetEvent ==> QLayoutPrivate::doResize ==> QBoxLayout::setGeometry ==> QWidgetItem::setGeometry ==> QWidget::setGeometry void QWidget::setVisible(bool visible) { ... // QWidget上有layout则会调用此,进行第一次布局计算 if (d->layout) d->layout->activate(); ... if (isWindow() || parentWidget()->isVisible()) { d->show_helper(); ... } ... } void QWidgetPrivate::show_helper() { ... sendPendingMoveAndResizeEvents(); ... } void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates) { ... // QWidget 有移动QWidget窗口位置事件,则发送事件 if (q->testAttribute(Qt::WA_PendingMoveEvent)) { QMoveEvent e(data.crect.topLeft(), data.crect.topLeft()); QApplication::sendEvent(q, &e); q->setAttribute(Qt::WA_PendingMoveEvent, false); } // QWidget 有调整QWidget窗口大小事件,则发送事件 if (q->testAttribute(Qt::WA_PendingResizeEvent)) { QResizeEvent e(data.crect.topLeft(), QSize()); QApplication::sendEvent(q, &e); q->setAttribute(Qt::WA_PendingResizeEvent, false); } ... // 调整子QWidget窗口的位置和大小 for (int i = 0; i ... // QWidget 上有layout则把事件发送到layout中进行处理 if (QLayout *layout = widget->d_func()->layout) { layout->widgetEvent(e); } ... } void QLayout::widgetEvent(QEvent *e) { ... switch (e->type()) { case QEvent::Resize: if (d->activated) { QResizeEvent *r = (QResizeEvent *)e; d->doResize(r->size()); } else { activate(); } break; case QEvent::ChildRemoved: ... break; case QEvent::LayoutRequest: if (static_cast(parent())->isVisible()) activate(); break; default: break; } } void QBoxLayout::setGeometry(const QRect &r) { ... ... } |
CopyRight 2018-2019 实验室设备网 版权所有 |