En esta página

Aplicación de cámara QML

Esta aplicación basada en Qt Quick muestra cómo utilizar la API para capturar una imagen fija o un vídeo.

Aplicación de cámara en modo horizontal con vista previa en directo y controles de captura

Este ejemplo muestra cómo acceder a las funciones de la cámara a través de QML. Muestra cómo cambiar la configuración y capturar imágenes o vídeo.

Ejecución del ejemplo

Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.

Estructura de la aplicación

La mayor parte del código QML de este ejemplo soporta la interfaz de usuario. Los tipos personalizados que soportan los requisitos se han implementado utilizando controles existentes de Qt Quick.

Uso de la orientación de la pantalla para seleccionar el diseño

La lógica del estado de orientación y disposición de los controles está encapsulada en un Item separado, controlLayout como se muestra a continuación:

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

Los objetos stillControls y videoControls se enlazan a las propiedades state y buttonsWidth de este elemento, como se muestra en 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
}

Para ayudar a la depuración, se registra un mensaje sobre el cambio de estado del diseño.

Este es el diseño del retrato:

Aplicación de cámara en modo retrato con vista previa en directo y controles de captura

Puede ver que la propiedad state se define inicialmente como PhotoCapture.

A continuación, los propios states se definen así:

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

Controles de captura

Los controles de captura se implementan en PhotoCaptureControls.qml y VideoCaptureControls.qml. Cada uno de ellos se basa en un FocusScope que define las dimensiones comunes de los botones y los márgenes que utilizan los botones de control y, a continuación, declara los botones.

Esto genera una columna en la parte derecha de la pantalla que incluye, enumerados de arriba a abajo, los siguientes controles:

  • Un botón Capture o Record, que inicia la captura.
  • Un botón capture properties que muestra el icono del modo de balance de blancos seleccionado en ese momento y que, al pulsarlo, utiliza una ventana emergente para mostrar los iconos de las siguientes opciones:
    • Modo de flash (si está disponible)
    • Modos de balance de blancos
    • Compensación de la exposición
  • Un botón View, una vez que se ha capturado algo.
  • Un botón que muestra el dispositivo de captura seleccionado en ese momento y, al pulsarlo, proporciona una lista de dispositivos disponibles a los que cambiar, mediante una ventana emergente.
  • Un botón Switch To, que muestra el modo de captura alternativo (vídeo o foto) en función de la selección activa en ese momento y cambia de modo al pulsarlo.
  • Un botón Quit, que sale de la aplicación.

Panel de control de captura de fotos

Panel de control de captura de vídeo

Captura de imágenes

El botón que activa esto está definido en CameraButton.qml: pero su interacción con la cámara está en los tipos de controles, veamos PhotoCaptureControls:

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

Control de zoom

Implementado en ZoomControl.qml el tipo ZoomControl se basa en un Item y crea una barra que representa el nivel de zoom, que también puede ser arrastrada. Utiliza un método de cálculo exponencial para determinar el factor de zoom dada la posición del grove.

La barra sólo es visible si elZoominicial es mayor que 1. Esto significa que la cámara actualmente activa tiene una función de zoom.

Barra de nivel de zoom ajustable

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

En PhotoCaptureControls.qml y VideoCaptureControls.qml la señal zoomTo ajustará la propiedad zoomFactor de la cámara seleccionada al valor calculado target, además de actualizar la barra 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
}

Control de flash y antorcha

Alterna entre los modos Flash y Antorcha

Definido en FlashControl.qml, permite seleccionar el modo de flash y la función de linterna mediante un interruptor. Al igual que con el control de zoom, los interruptores sólo son visibles en la parte superior de la ventana de vista previa si el dispositivo activo admite estas funciones.

Aquí comprobamos si las funciones están soportadas:

required property Camera camera

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

Aquí implementamos el interruptor flashModeControl, que también controla directamente el dispositivo Cámara.

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
}

El control de la antorcha se implementa de forma similar.

Proyecto de ejemplo @ 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.