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.

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:

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
CaptureoRecord, que inicia la captura. - Un botón
capture propertiesque 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.


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.

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

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