QWidget 之paint部分杂记

本文回顾了Qt从4.0到4.8版本的发展历程,重点介绍了每个版本中引入的关键特性和改进,包括双缓冲机制、延时控件创建、AlienWidget、透明窗口支持及图形效果等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt 4.0

automatically double-buffers

Qt 4.1

QWidget::autoFillBackground

Qt 4.2

delayed widget creation (DWC)

stylesheet

Qt 4.3

QWidget::render

Qt 4.4

Alien Widget

Qt 4.5

Translucent Windows

Qt 4.6

widget's graphics effect

Qt 4.8

lighthouse (qpa)

Qt4.0

  • 在Qt 4.0中,启用双缓冲,不必在paintEvent()中编写双缓冲代码来避免闪烁。

Qt4.1

  • 在Qt 4.1中,通过启用背景自动传递(propagation),widget不再有任何默认的背景。引入backingstore这个东西。



Qt4.2

  • 在Qt 4.2中,延时控件创建(delayed widget creation)的引入,使得widget可以在没有真实窗口句柄的情况下被创建。

QWindowSurface 与 QWidgetBackingStore

Even though QWidget is a QPaintDevice subclass, one will never render directly into a QWidget’s surface. Instead, during the paintEvent, the painting is redirected to an offscreen surface which is represented by the internal class QWindowSurface.

QWidgetBackingStore is responsible for figuring out which parts of the window surface needs to be updated prior to showing it to screen, so its really a repaint manager.

When the concept of backingstore was introduced in Qt 4.1, the two classes were the same, but the introduction of more varying ways to get content to screen made us split it in two.

Qt4.4

  • 在Qt 4.4中,Alien Widget诞生了,这样一来,Window和Widget尽管仍是同一个类,却是不同的东西。Window负责与窗口系统的联系。Alien被号称是所有闪烁的终结者,见Qt Invaded By Aliens — The End of All Flicker

Qt::WA_NativeWindow

创建原生窗体,即带句柄

Qt::WA_PaintOnScreen

强制创建原生窗体

Qt::Window

顶级窗口,必须是原生窗体 (?)

QGLWidget

必须是原生窗体

如果一个widget已经是alien Widget,如果对其设置上述标志,或者对其调用winId()函数,都会导致其重新创建为一个native widget。

Qt4.5

  • 在Qt 4.5中,graphics system的概念被引入(比如选项有:raster|opengl|x11|native 等)。引人了一个Qt::WA_TranslucentBackground 属性,这个东西和QWidget::setWindowOpacity()有些比较容易混哈。

QWidget::setWindowOpacity()函数,设置窗体(即:isWindow()为真的widget)的整体不透明度, 从0.0到1.0之间, 值越大越不透明。

Qt::WA_TranslucentBackground,这个属性每个QWidget都可以单独设置。不被绘制的区域(背景)都是透明的,绘制的区域的透明程度通过颜色或图片的Alpha Channel值来控制。

Qt4.6

  • 在Qt 4.6中,graphics effect被引入。但是,现在,已经不建议使用:

Graphics Effects
State: Deprecated
Reasoning: flawed design, we don’t recommend taking maintainership of this code.

QGraphicsEffect 的子类需要重新实现draw()函数。

以安装了QGraphicsOpacityEffect了QWidget为例,当每次需要重绘时,QWidgetPrivate::drawWidget()不是发送QPaintEvent事件,以调用我们的paintEvent()函数;而是调用QGraphicsOpacityEffect的draw()函数,该函数内,通过QWidget::render()调用paintEvent()将内容绘制在一个QPixmap中,而后设置QPainter的不透明度,绘制QPixmap到目标。

Qt4.8

  • 在Qt 4.8中,正式引入lighthouse了,...

参考


Qt中,要在QWidget中使用paintEvent()函数绘制一个按钮,并为其绑定信号和槽函数,你可以按照以下步骤操作: 1. 创建自定义按钮类,继承自QWidget: ```cpp class CustomButton : public QWidget { public: CustomButton(QWidget* parent = nullptr) : QWidget(parent), buttonClicked(false) {} protected: void paintEvent(QPaintEvent*) override { QPainter painter(this); // 绘制按钮背景 painter.setBrush(Qt::white); painter.drawRoundedRect(rect(), 5, 5); // 绘制蓝色边框 painter.setPen(Qt::blue); painter.drawRect(rect()); // 按钮文字 painter.setPen(Qt::black); QFontMetrics metrics(painter.font()); int textWidth = metrics.width(text); int textHeight = metrics.height(); painter.drawText(rect().adjusted(-textWidth / 2, -textHeight / 2, 0, 0), Qt::AlignCenter, text); // 按钮状态指示 if (buttonClicked) { painter.fillRect(rect(), QColor(50, 170, 255)); // 点击后的颜色 } } private slots: void onClicked() { buttonClicked = !buttonClicked; // 修改按钮状态 emit clickedSignal(); // 发送信号通知槽函数 } signals: void clickedSignal(); // 声明信号 private: bool buttonClicked; QString text; // 设定按钮文本 }; ``` 2. 使用该自定义按钮,并在其上绑定点击事件: ```cpp CustomButton *customButton = new CustomButton; customButton->move(50, 50); customButton->resize(100, 50); customButton->setText("Click Me"); connect(customButton, &CustomButton::clickedSignal, this, &MainWindow::onButtonClick); // 连接信号和槽函数 customButton->setMouseTracking(true); // 开启鼠标跟踪以便捕捉点击 customButton->setStyleSheet("background-color: white; border-radius: 5px; border: 1px solid blue;"); customButton->onClicked(); // 初始化按钮状态 ``` 在这里,`onClicked()`是一个槽函数,当按钮被点击时会被调用;`clickedSignal()`是自定义的信号,当按钮状态改变时发出。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值