Sur cette page

Application QML Camera

Cette application basée sur l'Qt Quick e montre comment utiliser l'API pour capturer une image fixe ou une vidéo.

Application Appareil photo en mode paysage affichant l'aperçu en direct et les commandes de prise de vue

Cet exemple montre comment accéder aux fonctions de l'appareil photo via QML. Il explique comment modifier les paramètres et capturer des images ou des vidéos.

Exécution de l'exemple

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

Structure de l'application

La majeure partie du code QML de cet exemple concerne l’interface utilisateur. Les types personnalisés répondant aux exigences ont été implémentés à l’aide des contrôles Qt Quick existants.

Utilisation de l’orientation de l’écran pour sélectionner la mise en page

La logique relative à l’orientation et à l’état de la mise en page des contrôles est encapsulée dans un élément distinct, controlLayout, comme suit :

Item {
    id: controlLayout

    readonly property bool isMobile: Qt.platform.os === "android" || Qt.platform.os === "ios"
    readonly property bool isLandscape: Screen.desktopAvailableWidth >= Screen.desktopAvailableHeight
    property int buttonsWidth: state === "MobilePortrait" ? Screen.desktopAvailableWidth / 3.4 : 114

    states: [
        State {
            name: "MobileLandscape"
            when: controlLayout.isMobile && controlLayout.isLandscape
        },
        State {
            name: "MobilePortrait"
            when: controlLayout.isMobile && !controlLayout.isLandscape
        },
        State {
            name: "Other"
            when: !controlLayout.isMobile
        }
    ]

    onStateChanged: {
        console.log("State: " + controlLayout.state)
    }
}

Les objets ` stillControls ` et ` videoControls ` sont tous deux liés aux propriétés ` state ` et ` buttonsWidth ` de cet `Item`, comme illustré dans stillControls:

PhotoCaptureControls {
    id: stillControls
    state: controlLayout.state
    anchors.fill: parent
    buttonsWidth: controlLayout.buttonsWidth
    buttonsPanelPortraitHeight: cameraUI.buttonsPanelPortraitHeight
    buttonsPanelWidth: cameraUI.buttonsPanelLandscapeWidth
    captureSession: captureSession
    visible: (cameraUI.state === "PhotoCapture")
    onPreviewSelected: cameraUI.state = "PhotoPreview"
    onVideoModeSelected: cameraUI.state = "VideoCapture"
    previewAvailable: imageCapture.preview.length !== 0
}

Pour faciliter le débogage, un message signalant le changement d’état de la mise en page est enregistré dans le journal.

Voici la mise en page « portrait » :

Application Appareil photo en mode portrait affichant un aperçu en direct et les commandes de prise de vue

Vous pouvez constater que la propriété « state » est initialement définie sur « PhotoCapture ».

Les éléments d’ states sont ensuite définis comme suit :

states: [
    State {
        name: "PhotoCapture"
        StateChangeScript {
            script: {
                camera.start()
            }
        }
    },
    State {
        name: "PhotoPreview"
    },
    State {
        name: "VideoCapture"
        StateChangeScript {
            script: {
                camera.start()
            }
        }
    },
    State {
        name: "VideoPreview"
        StateChangeScript {
            script: {
                camera.stop()
            }
        }
    }
]

Contrôles pour la capture

Les contrôles de capture sont implémentés dans les fichiers ` PhotoCaptureControls.qml ` et `VideoCaptureControls.qml`. Chacun d'entre eux s'appuie sur un fichier ` FocusScope ` qui définit les dimensions et les marges communes des boutons utilisées par les boutons du contrôle, puis déclare ces boutons.

Cela génère une colonne sur le côté droit de l’écran qui comprend, de haut en bas, les contrôles suivants :

  • Un bouton « Capture » ou « Record », qui lance la capture.
  • Un bouton « capture properties » qui affiche l'icône du mode de balance des blancs actuellement sélectionné et qui, lorsqu'on appuie dessus, ouvre une fenêtre contextuelle affichant les icônes des options suivantes :
    • Mode flash (si disponible)
    • Modes de balance des blancs
    • Compensation d’exposition
  • Un bouton « View », une fois la capture effectuée.
  • Un bouton qui affiche le périphérique de capture actuellement sélectionné et qui, lorsqu'on appuie dessus, affiche une liste des périphériques disponibles vers lesquels basculer, via une fenêtre contextuelle.
  • Un bouton d'Switch To qui affiche le mode de capture alternatif (vidéo ou photo) en fonction de la sélection actuellement active et qui permet de changer de mode lorsqu'on appuie dessus.
  • Un bouton d'Quit, qui permet de quitter l'application.

Panneau de commande de la capture photo

Panneau de commande de capture vidéo

Capture d’image

Le bouton qui déclenche cette action est défini dans CameraButton.qml : mais son interaction avec l’appareil photo se trouve dans les types de contrôles ; examinons PhotoCaptureControls :

CameraButton {
    text: "Capture"
    implicitWidth: captureControls.buttonsWidth
    visible: captureControls.captureSession.imageCapture.readyForCapture
    onClicked: captureControls.captureSession.imageCapture.captureToFile("")
}

Contrôle du zoom

Implémenté dans ZoomControl.qml, le type ZoomControl est basé sur un Item et crée une barre représentant le niveau de zoom, qui peut également être déplacée. Il utilise une méthode de calcul exponentielle pour déterminer le facteur de zoom en fonction de la position de l’ grove.

La barre n’est visible que si la valeur initialZoom est supérieure à 1. Cela signifie que la caméra actuellement active dispose d’une fonction de zoom.

Barre de réglage du niveau de zoom

Item {
    id : zoomControl
    property real currentZoom : 1
    property real maximumZoom : 1
    property real minimumZoom : 1
    signal zoomTo(real target)

    visible: zoomControl.maximumZoom > zoomControl.minimumZoom

    MouseArea {
        id : mouseArea
        anchors.fill: parent

        property real initialZoom : 0
        property real initialPos : 0

        onPressed: {
            initialPos = mouseY
            initialZoom = zoomControl.currentZoom
        }

        onPositionChanged: {
            if (pressed) {
                var target = initialZoom * Math.pow(5, (initialPos-mouseY)/zoomControl.height);
                target = Math.max(zoomControl.minimumZoom, Math.min(target, zoomControl.maximumZoom))
                zoomControl.zoomTo(target)
            }
        }
    }

    Item {
        id : bar
        x : 16
        y : parent.height/4
        width : 24
        height : parent.height/2

        Rectangle {
            anchors.fill: parent

            smooth: true
            radius: 8
            border.color: "white"
            border.width: 2
            color: "black"
            opacity: 0.3
        }

        Rectangle {
            id: groove
            x : 0
            y : parent.height * (1.0 - (zoomControl.currentZoom-zoomControl.minimumZoom) / (zoomControl.maximumZoom-zoomControl.minimumZoom))
            width: parent.width
            height: parent.height - y
            smooth: true
            radius: 8
            color: "white"
            opacity: 0.5
        }

        Text {
            id: zoomText
            anchors {
                left: bar.right; leftMargin: 16
            }
            y: Math.min(parent.height - height, Math.max(0, groove.y - height / 2))
            text: "x" + Math.round(zoomControl.currentZoom * 100) / 100
            font.bold: true
            color: "white"
            style: Text.Raised; styleColor: "black"
            opacity: 0.85
            font.pixelSize: 18
        }
    }
}

Dans PhotoCaptureControls.qml et VideoCaptureControls.qml, le signal « zoomTo » définit la propriété « zoomFactor » de la caméra sélectionnée sur la valeur calculée de « target », tout en mettant à jour la barre du ZoomControl.

ZoomControl {
    x : 0
    y : 0
    width : 100
    height: parent.height - (flashControl.visible * flashControl.height) -
            (captureControls.state === "MobilePortrait" ? buttonPaneShadow.height : 0)

    currentZoom: captureControls.camera.zoomFactor
    maximumZoom: captureControls.camera.maximumZoomFactor
    minimumZoom: captureControls.camera.minimumZoomFactor
    onZoomTo: (target) => captureControls.camera.zoomFactor = target
}

Contrôle du flash et de la lampe torche

Basculer entre le mode « Flash » et le mode « Lampe de poche »

Défini dans ` FlashControl.qml `, ce signal permet de sélectionner le mode flash et d’activer ou désactiver la fonction lampe de poche à l’aide d’un commutateur. Comme pour le contrôle du zoom, les commutateurs ne sont visibles au-dessus de la fenêtre d’aperçu que si l’appareil actif prend en charge ces fonctions.

Nous vérifions ici si ces fonctions sont prises en charge :

required property Camera camera

property bool mIsFlashSupported: camera.isFlashModeSupported(Camera.FlashOn)
property bool mIsTorchSupported: camera.isTorchModeSupported(Camera.TorchOn)

Nous implémentons ici le commutateur « flashModeControl », qui contrôle également directement l’appareil photo.

Switch {
    id: flashModeControl
    visible: topItem.mIsFlashSupported
    checked: topItem.camera.flashMode === Camera.FlashOn
    opacity: checked ? 0.75 : 0.25
    text: "Flash"

    contentItem: Text {
        text: flashModeControl.text
        color: "white"
        leftPadding: flashModeControl.indicator.width + flashModeControl.spacing
    }

    onClicked: topItem.camera.flashMode = checked ? Camera.FlashOn : Camera.FlashOff
}

Le contrôle de la lampe torche est implémenté de manière similaire.

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.