QML-Video-Beispiel

Transformieren von Video- und Kamerasucherinhalten.

QML Video demonstriert die verschiedenen Transformationen (Verschieben; Größenänderung; Drehen; Änderung des Seitenverhältnisses), die auf die QML-Typen VideoOutput und Camera angewendet werden können.

Es zeigt auch, wie nativer Code mit QML kombiniert werden kann, um erweiterte Funktionen zu implementieren - in diesem Fall wird C++-Code verwendet, um die QML-Bildrate zu berechnen. Dieser Wert wird in QML in einem halbtransparenten Element gerendert, das den Videoinhalt überlagert.

Das folgende Bild zeigt die Anwendung, die die Video-Overlay-Szene ausführt, die ein Dummy-Overlay-Element erstellt (nur ein halbtransparentes Rectangle), das sich über das Element VideoOutput bewegt.

Ausführen des Beispiels

Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.

Struktur der Anwendung

Die Datei Main.qml erstellt eine Benutzeroberfläche, die die folgenden Elemente enthält:

  • Zwei Button Instanzen, von denen jede einen Dateinamen anzeigt und zum Starten einer FileDialog verwendet werden kann.
  • Eine Beendigung Button.
  • Eine SceneSelectionPanel, die eine blätterbare Liste mit den verfügbaren Szenen darstellt.
  • Unten links befindet sich ein Element, das die QML-Wiederholungsrate anzeigt - die obere Zahl ist die momentane Bildrate und die untere Zahl ist der Durchschnitt der letzten Sekunde.

Jede Szene in der Flickable-Liste ist in einer eigenen QML-Datei implementiert - zum Beispiel ist die Video-Basisszene (die nur ein statisches VideoOutput in der Mitte des Bildschirms anzeigt) in der Datei VideoBasic.qml implementiert. Wie Sie aus dem Code ersehen können, macht dies von einer Art Vererbung Gebrauch; ein Element VideoBasic...

SceneBasic {
    contentType: "video"
}

... ist vom Typ SceneBasic...

import QtQuick
import QtQuick.Controls

Scene {
    id: root
    property string contentType
    ...
    Content {
        id: content
    ...
    }

    Label {
        anchors {
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            margins: 20
        }
        text: content.started ? qsTr("Tap the screen to stop content")
                              : qsTr("Tap the screen to start content")
        z: 2.0
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            if (content.started)
                content.stop()
            else
                content.start()
        }
    }

    Component.onCompleted: root.content = content
}

... der selbst ein Scene ist:

import QtQuick
import QtQuick.Controls

Rectangle {
    id: root
    ...
    property QtObject content
    ...
    Button {
        id: closeButton
        anchors {
            top: parent.top
            right: parent.right
            margins: root.margins
        }
        z: 2.0
        text: qsTr("Back")
        onClicked: root.close()
    }
}

SceneBasic beschreibt die Struktur und das Verhalten der Szene, ist aber unabhängig von der Art des Inhalts, der angezeigt werden soll - dieser wird durch Content abstrahiert.

Dieses Muster ermöglicht es uns, einen bestimmten Anwendungsfall zu definieren (in diesem Fall die einfache Anzeige eines statischen Inhalts) und diesen Anwendungsfall dann sowohl für Videoinhalte (VideoBasic) als auch für Kamerainhalte ({CameraBasic}) zu instanziieren. Dieser Ansatz wird zur Implementierung vieler anderer Szenen verwendet - zum Beispiel wird "den Inhalt wiederholt von links nach rechts und wieder zurück schieben" durch SceneMove implementiert, auf dem VideoMove und CameraMove basieren.

Abhängig vom Wert der Eigenschaft contentType in der obersten Szeneninstanz erzeugt das eingebettete Element Content entweder ein Element MediaPlayer oder ein Element Camera.

Berechnen und Anzeigen der QML-Malrate

Die QML-Malrate wird von der Klasse FrequencyMonitor berechnet, die einen Strom von Ereignissen (die über den notify()-Slot empfangen werden) in eine momentane und eine gemittelte Frequenz umwandelt:

class FrequencyMonitor : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY
                       instantaneousFrequencyChanged)
    Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged)

public:
    ...
    static void qmlRegisterType();

public slots:
    Q_INVOKABLE void notify();
};

Die FrequencyMonitor-Klasse wird in QML wie folgt dargestellt

void FrequencyMonitor::qmlRegisterType()
{
    ::qmlRegisterType<FrequencyMonitor>("FrequencyMonitor", 1, 0, "FrequencyMonitor");
}

und ihre Daten werden angezeigt, indem ein QML-Element namens FrequencyItem wie folgt definiert wird:

import FrequencyMonitor 1.0

Rectangle {
    id: root
    ...
    function notify() {
        monitor.notify()
    }

    FrequencyMonitor {
        id: monitor
        onAverageFrequencyChanged: {
            averageFrequencyText.text = monitor.averageFrequency.toFixed(2)
        }
    }

    Text {
        id: labelText
        anchors {
            left: parent.left
            top: parent.top
            margins: 10
        }
        color: root.textColor
        font.pixelSize: 0.6 * root.textSize
        text: root.label
        width: root.width - 2*anchors.margins
        elide: Text.ElideRight
    }

    Text {
        id: averageFrequencyText
        anchors {
            right: parent.right
            bottom: parent.bottom
            margins: 10
        }
        color: root.textColor
        font.pixelSize: root.textSize
    }
}

Das Ergebnis sieht wie folgt aus:

Es bleibt nur noch, das Signal afterRendering() des QQuickView -Objekts mit einer JavaScript-Funktion zu verbinden, die schließlich frequencyItem.notify() aufruft:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    ...
    QQuickView viewer;
    ...
    QQuickItem *rootObject = viewer.rootObject();
    ...
    QObject::connect(&viewer, SIGNAL(afterRendering()), rootObject, SLOT(qmlFramePainted()));

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.