本示例说明如何使用QPainter进行渲染以创建基于QWindow的最小应用程序。
Qt组件推荐:
- QtitanRibbon| 下载试用: 遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
- QtitanChart | 下载试用 :是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。并且支持所有主要的桌面。
- QtitanNavigation | 下载试用 :模拟Microsoft Dynamics CRM-2016/Office 365导航界面和一组控件改善Qt.C ++应用程序用户体验的QtitanNavigation组件。
本示例说明如何使用QPainter进行渲染以创建基于QWindow的最小应用程序。
应用程序入口点
int main(int argc, char **argv){ QGuiApplication app(argc, argv); RasterWindow window; window.show(); return app.exec();}
基于QWindow的应用程序的入口点是QGuiApplication类。它管理着GUI应用程序的控制流程和主要设置。我们传递命令行参数,这些参数可以用来拾取某些系统范围的选项。
从那里,我们继续创建我们的窗口实例,然后调用QWindow::show()函数来告诉窗口系统,现在应该让这个窗口在屏幕上可见。
一旦完成,我们进入应用程序的事件循环,这样应用程序就可以运行了。
RasterWindow声明
#include <QtGui>class RasterWindow : public QWindow{ Q_OBJECTpublic: explicit RasterWindow(QWindow *parent = 0); virtual void render(QPainter *painter);public slots: void renderLater(); void renderNow();protected: bool event(QEvent *event) override; void resizeEvent(QResizeEvent *event) override; void exposeEvent(QExposeEvent *event) override;private: QBackingStore *m_backingStore;};
我们首先要加入<QtGui>头。这意味着我们可以使用Qt GUI模块中的所有类。如果喜欢的话,也可以单独包含类。
RasterWindow类直接对QWindow进行子类化,并提供了一个构造函数,它允许窗口成为另一个QWindow的子窗口。无父类的QWindow在窗口系统中显示为顶层窗口。
该类声明了一个QBackingStore,我们用它来管理基于QPainter的图形的窗口回缓冲区。
栅格窗口在其他一些例子中也被重用,并增加了一些辅助函数,比如renderLater()。
RasterWindow实施
RasterWindow::RasterWindow(QWindow *parent) : QWindow(parent) , m_backingStore(new QBackingStore(this)){ setGeometry(100, 100, 300, 200);}
在构造函数中,我们创建后备存储,并将应管理的窗口实例传递给后备存储。我们还设置了初始窗口的几何形状。
void RasterWindow::exposeEvent(QExposeEvent *){ if (isExposed()) renderNow();}
在创建的窗口上调用QWindow::show()后不久,会调用虚拟函数QWindow::exposeEvent()来通知我们窗口在窗口系统中的曝光度发生了变化。该事件包含了暴露的子区域,但由于我们每次都会绘制整个窗口,所以我们并没有使用这个函数。
函数QWindow::isExposed()将告诉我们窗口是否显示。我们需要这个函数,因为当窗口在窗口系统中变得模糊时,exposeEvent也会被调用。如果窗口正在显示,我们调用renderNow()来立即绘制窗口。我们希望立即绘制,这样我们就可以给系统呈现一些视觉内容。
void RasterWindow::resizeEvent(QResizeEvent *resizeEvent){ m_backingStore->resize(resizeEvent->size());}
保证在窗口显示在屏幕上之前调用resize事件,并且在窗口在屏幕上调整窗口大小时也会调用该事件。我们使用它来调整后台缓冲区的大小,并将渲染推迟到相应的/随后的暴露事件。
void RasterWindow::renderNow(){ if (!isExposed()) return; QRect rect(0, 0, width(), height()); m_backingStore->beginPaint(rect); QPaintDevice *device = m_backingStore->paintDevice(); QPainter painter(device); painter.fillRect(0, 0, width(), height(), QGradient::NightFade); render(&painter); painter.end(); m_backingStore->endPaint(); m_backingStore->flush(rect);}
renderNow函数设置了QWindow使用QPainter渲染其内容所需的内容。由于被遮挡的窗口是不可见的,所以如果该窗口在窗口系统中没有暴露,我们就会中止。例如,当另一个窗口完全遮挡住这个窗口时,就会发生这种情况。
我们通过调用QBackingStore::beginPaint()来开始绘制我们想要绘制的区域。然后我们得到后方缓冲区的QPaintDevice,并创建一个QPainter来渲染到该绘画设备。
为了使之前的渲染留下的痕迹无效,并以一个干净的缓冲区开始,我们用白色填充整个缓冲区。然后我们调用虚拟的render()函数,对这个窗口进行实际的绘制。
绘制完成后,我们调用endPaint()来表示我们已经完成了渲染,并使用QBackingStore::flush()来呈现后面缓冲区中的内容。
void RasterWindow::render(QPainter *painter){ painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));}
渲染函数包含了窗口的绘制代码,在这个最小的例子中,我们只在中间绘制 “QWindow “这个字符串。在这个最小的例子中,我们只在中间绘制 “QWindow “这个字符串。
异步渲染
void RasterWindow::renderLater(){ requestUpdate();}我们经历了几个需要立即重绘窗口的地方。有些情况下,这样做并不可取,而是让应用程序返回事件循环,并将重绘安排在以后进行。我们通过请求更新,使用QWindow::requestUpdate()来实现,当系统准备好重新绘制时,更新将被传递。
bool RasterWindow::event(QEvent *event){ if (event->type() == QEvent::UpdateRequest) { renderNow(); return true; } return QWindow::event(event);}我们重新实现虚拟QObject::event()函数来处理更新事件。当事件发生时,我们调用renderNow()来立即渲染窗口。
====================================================
想要了解或购买Qt正版授权的朋友,欢迎咨询官方客服
Qt技术交流群现已开通,QQ搜索群 “765444821”或者扫描下方二维码即可加入
![]()
标签:
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!