Beispiel für ein Rasterfenster

Dieses Beispiel zeigt, wie man eine minimale, auf QWindow basierende Anwendung erstellt, die QPainter zum Rendern verwendet.

Einstiegspunkt der Anwendung

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

    RasterWindow window;
    window.show();

    return app.exec();
}

Der Einstiegspunkt für eine QWindow basierte Anwendung ist die Klasse QGuiApplication. Sie verwaltet den Kontrollfluss und die wichtigsten Einstellungen der GUI-Anwendung. Wir übergeben die Befehlszeilenargumente, die verwendet werden können, um bestimmte systemweite Optionen zu übernehmen.

Anschließend erstellen wir unsere Fensterinstanz und rufen die Funktion QWindow::show() auf, um dem Fenstersystem mitzuteilen, dass dieses Fenster nun auf dem Bildschirm sichtbar gemacht werden soll.

Sobald dies geschehen ist, treten wir in die Ereignisschleife der Anwendung ein, damit die Anwendung ausgeführt werden kann.

RasterWindow-Deklaration

#include <QtGui>
#include <QScopedPointer>

class RasterWindow : public QWindow
{
    Q_OBJECT
public:
    explicit RasterWindow(QWindow *parent = nullptr);

    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:
    QScopedPointer<QBackingStore> m_backingStore;
};

Wir beginnen damit, den <QtGui> Header einzubinden. Das bedeutet, dass wir alle Klassen im Modul Qt GUI verwenden können. Die Klassen können auch einzeln eingebunden werden, wenn dies gewünscht wird.

Die Klasse RasterWindow ist eine direkte Unterklasse von QWindow und bietet einen Konstruktor, mit dem das Fenster ein Unterfenster eines anderen QWindow sein kann. Elternlose QWindows werden im Fenstersystem als Top-Level-Fenster angezeigt.

Die Klasse deklariert eine QBackingStore, die wir verwenden, um den Rückpuffer des Fensters für QPainter basierte Grafiken zu verwalten.

Das Rasterfenster wird auch in einigen anderen Beispielen wiederverwendet und fügt einige Hilfsfunktionen hinzu, wie renderLater().

RasterWindow Implementierung

RasterWindow::RasterWindow(QWindow *parent)
    : QWindow(parent)
    , m_backingStore(new QBackingStore(this))
{
    setGeometry(100, 100, 300, 200);
}

Im Konstruktor erstellen wir den Backingstore und übergeben ihm die Fensterinstanz, die er verwalten soll. Wir legen auch die anfängliche Fenstergeometrie fest.

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

Kurz nach dem Aufruf von QWindow::show() für ein erstelltes Fenster wird die virtuelle Funktion QWindow::exposeEvent() aufgerufen, um uns mitzuteilen, dass sich die Exposition des Fensters im Windowing-System geändert hat. Das Ereignis enthält den belichteten Teilbereich, aber da wir ohnehin jedes Mal das gesamte Fenster zeichnen werden, machen wir davon keinen Gebrauch.

Die Funktion QWindow::isExposed() teilt uns mit, ob das Fenster sichtbar ist oder nicht. Wir brauchen dies, da das exposeEvent auch dann aufgerufen wird, wenn das Fenster im Windowing-System verdeckt wird. Wenn das Fenster sichtbar ist, rufen wir renderNow() auf, um das Fenster sofort zu zeichnen. Wir wollen es sofort zeichnen, damit wir dem System einen visuellen Inhalt präsentieren können.

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

Das resize-Ereignis wird garantiert aufgerufen, bevor das Fenster auf dem Bildschirm angezeigt wird, und wird auch aufgerufen, wenn die Größe des Fensters auf dem Bildschirm geändert wird. Wir verwenden dies, um die Größe des hinteren Puffers zu ändern, und verschieben das Rendern auf das entsprechende/folgende expose-Ereignis.

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

Die Funktion renderNow richtet ein, was für ein QWindow benötigt wird, um seinen Inhalt mit QPainter zu rendern. Da verdeckte Fenster nicht sichtbar sind, brechen wir ab, wenn das Fenster im Fenstersystem nicht sichtbar ist. Dies kann zum Beispiel der Fall sein, wenn ein anderes Fenster dieses Fenster vollständig verdeckt.

Wir beginnen mit dem Zeichnen, indem wir QBackingStore::beginPaint() für die Region aufrufen, die wir zeichnen wollen. Dann holen wir uns die QPaintDevice des Backbuffers und erstellen eine QPainter, um auf dieses Malgerät zu rendern.

Um die Spuren des vorherigen Renderings zu beseitigen und mit einem sauberen Puffer zu beginnen, füllen wir den gesamten Puffer mit der Farbe Weiß. Dann rufen wir die virtuelle Funktion render() auf, die das eigentliche Zeichnen dieses Fensters übernimmt.

Nachdem das Zeichnen abgeschlossen ist, rufen wir endPaint() auf, um zu signalisieren, dass wir mit dem Rendern fertig sind, und präsentieren den Inhalt im hinteren Puffer mit QBackingStore::flush().

void RasterWindow::render(QPainter *painter)
{
    painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
}

Die Render-Funktion enthält den Zeichencode für das Fenster. In diesem kleinen Beispiel wird nur die Zeichenkette "QWindow" in der Mitte gezeichnet.

Asynchrones Rendering

void RasterWindow::renderLater()
{
    requestUpdate();
}

Wir haben uns ein paar Stellen angesehen, an denen das Fenster sofort neu gezeichnet werden muss. Es gibt einige Fälle, in denen dies nicht wünschenswert ist. Stattdessen sollte die Anwendung zur Ereignisschleife zurückkehren und die Neuzeichnung für später planen. Wir erreichen dies, indem wir mit QWindow::requestUpdate() eine Aktualisierung anfordern, die dann geliefert wird, wenn das System bereit ist, das Fenster neu zu malen.

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

Wir reimplementieren die virtuelle Funktion QObject::event(), um das Aktualisierungsereignis zu behandeln. Wenn das Ereignis eintrifft, rufen wir renderNow() auf, um das Fenster sofort zu rendern.

Beispielprojekt @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.