文章目录
Application Entry Point
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
RasterWindow window;
window.show();
return app.exec();
}
Note: 示例里是QGuiApplication,我创建工程时默认为QApplication,不用更改,后面的也可以正常使用。
基于QWindow的应用程序的入口是QGuiApplication类。它管理GUI应用程序的控制流和主要设置。我们向其传递可用于选择某些系统范围的选项命令行参数。
从那里,我们继续创建我们的窗口实例,然后调用QWindow::show()函数来显示窗口。
完成之后,我们进入应用程序的事件循环,以便应用程序可以运行。
RasterWindow Declaration
#include <QtGui>
class RasterWindow : public QWindow
{
Q_OBJECT
public:
explicit RasterWindow(QWindow *parent = 0);
virtual void render(QPainter *painter);
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE;
private:
QBackingStore *m_backingStore;
bool m_update_pending;
};
我们首先包含头文件。这意味着我们可以使用Qt GUI模块中的所有类。如果需要的话,也可以单独添加相关类.
RasterWindow类直接子类化了QWindow,并提供了一个构造函数,允许该窗口成为另一个QWindow的子窗口。没有父级的QWindows在窗口系统中显示为顶级窗口。
这个类声明了一个QBackingStore,我们用它来管理基于QPainter的图形的窗口后台缓冲区。
栅格窗口在其他一些示例中也被重用,并添加了一些助手函数,如renderLater()。
RasterWindow Implementation`
void RasterWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
我们检查了几个需要立即重新油漆窗户的地方。在某些情况下,这样做是不可取的,而是让应用程序稍后返回事件循环。我们通过向自己发送偶数来实现这一点,然后当应用程序返回到QGuiApplication事件循环时,将发送偶数。为了避免在一个已经挂起的请求时发布新的请求,我们将这个状态存储在m_update_pending变量中。
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());
if (isExposed())
renderNow();
}
resize事件保证会在窗口显示在屏幕上之前被调用,也会在窗口在屏幕上调整大小时被调用。我们使用它来调整后台缓冲区的大小,并在我们可见的情况下调用renderNow()来立即更新屏幕上窗口的视觉表示。
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(), Qt::white);
render(&painter);
m_backingStore->endPaint();
m_backingStore->flush(rect);
}
renderNow函数设置QWindow使用QPainter渲染其内容所需要的内容。由于被遮挡的窗口将不可见,如果窗口在窗口系统中没有显示,我们将中止该窗口。例如,当另一个窗口完全遮蔽了该窗口时,可能会发生这种情况。
我们通过在我们想要绘制的区域上调用QBackingStore::beginPaint()来开始绘制。然后我们获取后台缓冲区的QPaintDevice,并创建一个QPainter来渲染到该油漆设备。
为了消除先前渲染留下的痕迹,并以一个干净的缓冲区开始,我们用白色填充整个缓冲区。然后我们调用virtual render()函数来绘制这个窗口。
绘制完成后,调用endPaint()表示绘制完成,并使用QBackingStore::flush()在后缓冲区中显示内容。
void RasterWindow::render(QPainter *painter)
{
painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
}
render函数包含窗口的绘图代码。在这个最小的例子中,我们只在中心绘制了字符串“QWindow”。
Rendering Asynchronously
void RasterWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
我们检查了几个需要立即重新油漆窗口的地方。在某些情况下,这样做是不可取的,而是让应用程序稍后返回事件循环。我们通过向自己发送偶数来实现这一点,然后当应用程序返回到QGuiApplication事件循环时,将发送偶数。为了避免在一个已经挂起的请求时发布新的请求,我们将这个状态存储在m_update_pending变量中。
bool RasterWindow::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
m_update_pending = false;
renderNow();
return true;
}
return QWindow::event(event);
}
我们重新实现虚拟QObject::event()函数来处理我们提交给自己的更新事件。当事件发生时,我们重置了挂起的更新标志,并调用renderNow()来立即呈现窗口。
运行效果
源代码
main.cpp
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "rasterwindow.h"
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
RasterWindow window;
window.show();
return app.exec();
}
rasterwindow.h
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef RASTERWINDOW_H
#define RASTERWINDOW_H
#include <QtGui>
class RasterWindow : public QWindow
{
Q_OBJECT
public:
explicit RasterWindow(QWindow *parent = 0);
virtual void render(QPainter *painter);
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE;
private:
QBackingStore *m_backingStore;
bool m_update_pending;
};
#endif // RASTERWINDOW_H
rasterwindow.cpp
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "rasterwindow.h"
RasterWindow::RasterWindow(QWindow *parent)
: QWindow(parent)
, m_update_pending(false)
{
m_backingStore = new QBackingStore(this);
create();
setGeometry(100, 100, 300, 200);
}
bool RasterWindow::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
m_update_pending = false;
renderNow();
return true;
}
return QWindow::event(event);
}
void RasterWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
{
m_backingStore->resize(resizeEvent->size());
if (isExposed())
renderNow();
}
void RasterWindow::exposeEvent(QExposeEvent *)
{
if (isExposed()) {
renderNow();
}
}
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(), Qt::white);
render(&painter);
m_backingStore->endPaint();
m_backingStore->flush(rect);
}
void RasterWindow::render(QPainter *painter)
{
painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
}
rasterwindow.pro (此文件可不用理会,正常创建项目就可,不用更改此文件)
include(rasterwindow.pri)
SOURCES += \
main.cpp
target.path = $$[QT_INSTALL_EXAMPLES]/gui/rasterwindow
INSTALLS += target