QML 相机应用程序
此基于Qt Quick 的应用程序演示了如何使用API拍摄静态图像或录制视频。

本示例演示了如何通过 QML 访问相机功能,并展示了如何更改设置以及拍摄静止图像或视频。
运行示例
您可以通过以下方式运行该示例:
- Qt Creator
打开Welcome 模式,并从Examples 中选择该示例。有关更多信息,请参阅Qt Creator :教程:构建和运行。
- Qt Extension for Visual Studio Code
在Command Palette 中执行Qt: Open Qt examples 命令,并从列表中选择该示例。有关更多信息,请参阅Qt Extension for Visual Studio Code :教程:构建和运行。
应用程序结构
本示例中的大部分 QML 代码用于支持用户界面。已利用现有的Qt Quick 控件实现了满足相关要求的自定义类型。
利用屏幕方向选择布局
屏幕方向和控件布局状态的逻辑封装在一个独立的 Item(controlLayout )中,如下所示:
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)
}
}stillControls 和videoControls 对象均绑定到该Item的state 和buttonsWidth 属性,如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
}为了支持调试,系统会记录一条关于布局状态变化的日志。
以下是纵向布局:

可以看到,state 属性初始值被设置为PhotoCapture 。
随后,states 本身被定义如下:
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()
}
}
}
]用于捕获的控件
用于捕获的控件在PhotoCaptureControls.qml 和VideoCaptureControls.qml中实现。它们均基于FocusScope ,该文件定义了控件按钮所使用的通用按钮尺寸和边距,随后声明了这些按钮。
这会在屏幕右侧生成一列控件,其中从上到下依次包含以下控件:
- 一个
Capture或Record按钮,用于启动捕获。 - 一个
capture properties按钮,用于显示当前所选白平衡模式的图标;按下该按钮时,会通过弹出窗口显示以下选项的图标:- 闪光灯模式(如有)
- 白平衡模式
- 曝光补偿
View按钮,在完成拍摄后显示。- 一个用于显示当前选定拍摄设备的按钮,按下后会通过弹出窗口提供可供切换的设备列表。
- 一个
Switch To按钮,根据当前的活动选择显示替代捕获模式(视频或照片),按下时切换模式。 - 一个
Quit按钮,用于退出应用程序。


图像拍摄
触发此功能的按钮在 CameraButton.qml 中定义:但其与相机的交互逻辑位于控件类型中,让我们看看 PhotoCaptureControls:
CameraButton {
text: "Capture"
implicitWidth: captureControls.buttonsWidth
visible: captureControls.captureSession.imageCapture.readyForCapture
onClicked: captureControls.captureSession.imageCapture.captureToFile("")
}变焦控件
ZoomControl 类型在ZoomControl.qml 中实现,基于 Item 构建,并生成一条表示变焦级别的滑动条,该滑动条支持拖动。它采用指数计算方法,根据grove 的位置来确定变焦倍数。
只有当 initialZoom 大于 1 时,该进度条才会显示。这意味着当前活动的相机具有变焦功能。

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
}
}
}在 PhotoCaptureControls.qml 和 VideoCaptureControls.qml 中,zoomTo 信号将把所选摄像机的zoomFactor 属性设置为计算出的target 值,并更新 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
}闪光灯和手电筒控制

该功能在FlashControl.qml 中定义,允许通过开关(Switch)选择闪光灯模式并切换手电筒功能。与变焦控制类似,只有当当前设备支持这些功能时,这些开关才会显示在预览窗口上方。
在此处,我们检查设备是否支持这些功能:
required property Camera camera
property bool mIsFlashSupported: camera.isFlashModeSupported(Camera.FlashOn)
property bool mIsTorchSupported: camera.isTorchModeSupported(Camera.TorchOn)在此我们实现了flashModeControl 开关,该开关还直接控制相机设备。
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
}手电筒控制的实现方式与此类似。
© 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.