QML-Kamera-Anwendung

Diese auf Qt Quick basierende Anwendung zeigt, wie die API verwendet wird, um ein Standbild oder ein Video aufzunehmen.

Dieses Beispiel zeigt, wie man über QML auf Kamerafunktionen zugreifen kann. Es zeigt, wie man Einstellungen ändert und Bilder oder Videos aufnimmt.

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

Der größte Teil des QML-Codes in diesem Beispiel unterstützt die Benutzeroberfläche. Benutzerdefinierte Typen, die die Anforderungen unterstützen, wurden unter Verwendung vorhandener Qt Quick Steuerelemente implementiert.

Verwendung der Bildschirmausrichtung zur Auswahl des Layouts

Die Logik für die Ausrichtung und das Layout der Steuerelemente ist in einem separaten Objekt gekapselt, controlLayout, wie folgt:

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

Die Objekte stillControls und videoControls sind beide an die Eigenschaften state und buttonsWidth dieses Elements gebunden, wie in stillControls gezeigt:

    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
    }

Um die Fehlersuche zu unterstützen, wird eine Meldung über die Änderung des Layoutstatus protokolliert.

Hier ist das Hochformat-Layout:

Wie Sie sehen, ist die Eigenschaft state zunächst als PhotoCapture festgelegt.

Dann werden die states selbst wie folgt definiert:

    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()
                }
            }
        }
    ]

Steuerelemente für das Capturing

Die Steuerelemente für die Aufzeichnung sind in PhotoCaptureControls.qml und VideoCaptureControls.qml implementiert. Sie basieren jeweils auf einer FocusScope, die die allgemeinen Abmessungen und Ränder der Schaltflächen definiert, die von den Schaltflächen des Steuerelements verwendet werden, und dann die Schaltflächen deklariert.

Dies erzeugt eine Spalte auf der rechten Seite des Bildschirms, die von oben nach unten die folgenden Steuerelemente enthält:

  • Eine Schaltfläche Capture oder Record, die die Erfassung einleitet.
  • Eine Schaltfläche capture properties, die das Symbol des aktuell ausgewählten Weißabgleichsmodus anzeigt und bei Betätigung ein Popup-Fenster mit den Symbolen der folgenden Optionen anzeigt:
    • Blitzmodus (falls verfügbar)
    • Weißabgleich-Modi
    • Belichtungskorrektur
  • Eine Taste View, sobald eine Aufnahme gemacht wurde.
  • Eine Schaltfläche, die das aktuell ausgewählte Aufnahmegerät anzeigt und beim Drücken eine Liste der verfügbaren Geräte anzeigt, zu denen man über ein Popup-Fenster wechseln kann.
  • Eine Schaltfläche Switch To, die je nach aktueller Auswahl den alternativen Aufnahmemodus (Video oder Foto) anzeigt und den Modus umschaltet, wenn sie gedrückt wird.
  • Eine Schaltfläche Quit, mit der die Anwendung beendet wird.

Bildaufnahme

Die Schaltfläche, die dies auslöst, ist in CameraButton.qml definiert: aber die Interaktion mit der Kamera ist in den Steuerelementtypen, schauen wir uns PhotoCaptureControls an:

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

Zoom-Steuerung

Der in ZoomControl.qml implementierte ZoomControl-Typ basiert auf einem Item und erzeugt einen Balken, der die Zoomstufe darstellt und der auch gezogen werden kann. Es verwendet eine exponentielle Berechnungsmethode, um den Zoomfaktor in Abhängigkeit von der Position des grove zu bestimmen.

Der Balken ist nur sichtbar, wenn initialZoom größer als 1 ist, d. h. die gerade aktive Kamera hat eine Zoomfunktion.

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

In PhotoCaptureControls.qml und VideoCaptureControls.qml setzt das Signal zoomTo die Eigenschaft zoomFactor der ausgewählten Kamera auf den berechneten Wert target und aktualisiert die ZoomControl-Leiste.

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

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

Blitz- und Taschenlampensteuerung

Definiert in FlashControl.qml ermöglicht dies die Auswahl des Blitzmodus und die Umschaltung der Taschenlampenfunktion über einen Schalter. Wie bei der Zoomsteuerung sind die Schalter nur dann oben im Vorschaufenster sichtbar, wenn das aktive Gerät diese Funktionen unterstützt.

Hier prüfen wir, ob die Funktionen unterstützt werden:

    property Camera cameraDevice
    property bool mIsFlashSupported: (cameraDevice && cameraDevice.active) ? cameraDevice.isFlashModeSupported(Camera.FlashOn) : false
    property bool mIsTorchSupported: (cameraDevice && cameraDevice.active) ? cameraDevice.isTorchModeSupported(Camera.TorchOn) : false

Hier implementieren wir den Schalter flashModeControl, der auch direkt das Kameragerät steuert.

        Switch {
            id: flashModeControl
            visible: flashControl.mIsFlashSupported
            opacity: checked ? 0.75 : 0.25
            text: "Flash"
            contentItem: Text {
                text: flashModeControl.text
                color: "white"
                leftPadding: flashModeControl.indicator.width + flashModeControl.spacing
            }

            onPositionChanged: {
                if (position) {
                    if (torchModeControl.checked)
                        torchModeControl.toggle();
                    flashControl.cameraDevice.flashMode = Camera.FlashOn

                } else {
                    flashControl.cameraDevice.flashMode = Camera.FlashOff
                }
            }
        }

Die Steuerung der Taschenlampe wird auf ähnliche Weise implementiert.

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.