Sur cette page

Exemple vidéo QML

Transformation du contenu vidéo et du viseur de l'appareil photo.

QML Video illustre les différentes transformations (déplacement, redimensionnement, rotation, modification du format d'image) pouvant être appliquées aux types QML ` VideoOutput ` et ` Camera `.

Il montre également comment le code natif peut être combiné avec QML pour implémenter des fonctionnalités plus avancées : dans ce cas précis, du code C++ est utilisé pour calculer la fréquence d’images QML. Cette valeur est affichée en QML sous la forme d’un élément semi-transparent superposé au contenu vidéo.

L’image suivante montre l’application exécutant la scène de superposition vidéo, qui crée un élément de superposition factice (simplement une Rectangle semi-transparente) se déplaçant sur l’élément VideoOutput.

Lecteur vidéo avec superposition semi-transparente

Exécution de l’exemple

Vous pouvez exécuter l’exemple à partir de :

Structure de l’application

Le fichier Main.qml crée une interface utilisateur comprenant les éléments suivants :

  • Deux instances d’ Button, dont chacune affiche un nom de fichier et peut être utilisée pour lancer une application FileDialog.
  • Un « exit » Button.
  • Un « SceneSelectionPanel », qui est une liste à faire défiler affichant les scènes disponibles.
  • En bas à gauche, un élément affichant la fréquence de rafraîchissement QML : le chiffre du haut correspond à la fréquence d’images instantanée et celui du bas à la moyenne sur la dernière seconde.

Panneau de sélection des scènes affichant la liste des scènes en mode vidéo et en mode appareil photo

Chaque scène de la liste défilable est implémentée dans son propre fichier QML. Par exemple, la scène « video-basic » (qui affiche simplement une « VideoOutput » statique au centre de l’écran) est implémentée dans le fichier « VideoBasic.qml ». Comme vous pouvez le constater dans le code, cela fait appel à une forme d’héritage : un élément « VideoBasic »…

SceneBasic {
    contentType: "video"
}

... est de type « 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
}

... qui est lui-même un Scene:

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 décrit la structure et le comportement de la scène, mais est indépendant du type de contenu qui sera affiché — celui-ci est géré de manière abstraite par Content.

Ce modèle nous permet de définir un cas d’utilisation particulier (dans ce cas, simplement afficher un contenu statique), puis d’instancier ce cas d’utilisation à la fois pour le contenu vidéo (VideoBasic) et pour le contenu de la caméra ({CameraBasic}). Cette approche est utilisée pour implémenter bon nombre d’autres scènes — par exemple, « faire glisser le contenu de gauche à droite et inversement de manière répétée » est implémenté par SceneMove, sur lequel s’appuient VideoMove et CameraMove.

En fonction de la valeur de la propriété contentType de l’instance de scène de niveau supérieur, l’élément intégré Content crée soit un élément MediaPlayer, soit un élément Camera.

Calcul et affichage de la fréquence de rafraîchissement QML

La fréquence de rafraîchissement QML est calculée par la classe FrequencyMonitor, qui transforme un flux d’événements (reçus via le slot notify()) en une fréquence instantanée et une fréquence moyenne :

class FrequencyMonitor : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY
                       instantaneousFrequencyChanged)
    Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged)
    ...
public slots:
    Q_INVOKABLE void notify();
};

La classe FrequencyMonitor est exposée à QML en ajoutant la macro QML_ELEMENT à la déclaration de la classe, comme indiqué ci-dessus, et ses données sont affichées en définissant un élément QML appelé FrequencyItem, comme ceci :

import frequencymonitor

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

Le résultat se présente comme suit :

Fréquence instantanée de 62,5 Hz et fréquence moyenne de 53,15 Hz

Il ne reste plus qu’à connecter le signal afterRendering() de l’objet QQuickView à une fonction JavaScript, qui appellera finalement frequencyItem.notify():

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

Exemple de projet sur code.qt.io

© 2026 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.