Raster Window Example of Qt

Application Entry Point

  int main(int argc, char **argv)
  {
      QGuiApplication app(argc, argv);

      RasterWindow window;
      window.show();

      return app.exec();
  }

Note: in the example, it is QGuiApplication. When I create a project, it is QApplication by default. It does not need to be changed. The later ones can also be used normally.

The entry of the application based on QWindow is the QGuiApplication class. It manages the control flow and main settings for GUI applications. We pass it command line parameters that can be used to select certain system wide options.

From there, we continue to create our window instance, and then call the QWindow::show() function to display the window.

After that, we enter the event loop of the application so that the application can run.

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;
  };

We first include the header file. This means that we can use all classes in the Qt GUI module. If necessary, you can also add related classes separately

RasterWindow class directly subclasses QWindow and provides a constructor that allows the window to become a child of another QWindow. QWindows without parent is displayed as a top-level window in the window system.

This class declares a QBackingStore, which we use to manage the window background buffer of QPainter based graphics.

The grid window has also been reused in other examples, and some helper functions have been added, such as renderLater().

RasterWindow Implementation`

  void RasterWindow::renderLater()
  {
      if (!m_update_pending) {
          m_update_pending = true;
          QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
      }
  }

We checked several places where the windows needed to be repainted immediately. In some cases, it is not advisable to do so, but to let the application return to the event loop later. We do this by sending ourselves an even number, which is then sent when the application returns to the QGuiApplication event loop. To avoid issuing a new request when a request has been suspended, we store this state in M_ update_ In the pending variable.

  void RasterWindow::exposeEvent(QExposeEvent *)
  {
      if (isExposed()) {
          renderNow();
      }
  }

Shortly after calling QWindow::show() on a created window, the virtual function QWindow::exposeEvent() will be called to inform us that the window display in the window system has changed. The event contains a sub area of the display, but since we will draw the entire window each time, we don't use it.

The function QWindow::isExposed() will tell us whether the window is being displayed. When the window becomes blurred in the window system, we also need to call exposeEvent. If the window is being displayed, we call renderNow() to draw the window immediately. We want to draw immediately so that we can present the system with some visual content.

  void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
  {
      m_backingStore->resize(resizeEvent->size());
      if (isExposed())
          renderNow();
  }

The resize event is guaranteed to be called before the window is displayed on the screen and when the window is resized on the screen. We use it to resize the background buffer and call renderNow() when we are visible to immediately update the visual representation of the window on the screen.

  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);
  }

The renderNow function sets what QWindow needs to render its content using QPainter. Because the blocked window will not be visible, if the window is not displayed in the window system, we will abort the window. This can happen, for example, when another window completely obscures the window.

We start painting by calling QBackingStore::beginPaint() in the area we want to paint. Then we get the QPaintDevice of the background buffer and create a QPainter to render to the paint device.

In order to eliminate the traces left by the previous rendering and start with a clean buffer, we fill the entire buffer with white. Then we call the virtual render() function to draw the window.

After completion of the rendering, call endPaint() to indicate that the rendering is completed and use QBackingStore::flush() to display the contents in the back buffer.

  void RasterWindow::render(QPainter *painter)
  {
      painter->drawText(QRectF(0, 0, width(),   height()), Qt::AlignCenter, QStringLiteral("QWindow"));
  }
render The function contains the drawing code for the window. In this minimal example, we only draw the string in the center“ QWindow". 

Rendering Asynchronously

  void RasterWindow::renderLater()
  {
      if (!m_update_pending) {
          m_update_pending = true;
          QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
      }
  }

We checked several places where the windows needed to be repainted immediately. In some cases, it is not advisable to do so, but to let the application return to the event loop later. We do this by sending ourselves an even number, which is then sent when the application returns to the QGuiApplication event loop. To avoid issuing a new request when a request has been suspended, we store this state in M_ update_ In the pending variable.

  bool RasterWindow::event(QEvent *event)
  {
      if (event->type() == QEvent::UpdateRequest) {
          m_update_pending = false;
          renderNow();
          return true;
      }
      return QWindow::event(event);
  }

We re implement the virtual QObject::event() function to handle the update events we submit to ourselves. When the event occurs, we reset the pending update flag and call renderNow() to render the window immediately.

Operation effect

source code

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 (this file can be ignored. You can create a project normally without changing this file)

  include(rasterwindow.pri)

  SOURCES += \
      main.cpp

  target.path = $$[QT_INSTALL_EXAMPLES]/gui/rasterwindow
  INSTALLS += target
 

Keywords: Qt

Added by jac38 on Fri, 14 Jan 2022 07:44:51 +0200