# 捕获图像
Camera元素的主要功能之一是可以用来拍照。 下面将在一个简单的定格动画应用程序中使用它。 通过构建应用程序,将学习如何显示取景器、在相机之间切换、拍摄照片以及跟踪拍摄的照片。
用户界面如下所示。 它由三个主要部分组成:在背景中,可以找到取景器;右侧,是一列按钮;底部,是拍摄的图像列表。 想法是拍摄一系列照片,然后单击Play Sequence(播放序列)按钮播放图像,创建一个简单的定格动画电影。

# 取景器
相机的取景器部分使用VideoOutput元素作为CaptureSession的视频输出通道。 CaptureSession依次使用Camera组件来配置设备,这将显示来自摄像机的实时视频流。
CaptureSession {
id: captureSession
videoOutput: output
camera: Camera {}
imageCapture: ImageCapture {
onImageSaved: function (id, path) {
imagePaths.append({"path": path})
listView.positionViewAtEnd()
}
}
}
VideoOutput {
id: output
anchors.fill: parent
}提示
可以通过使用专用的Camera属性(例如exposureMode、whiteBalanceMode或zoomFactor)对相机行为进行更多控制。
# 捕获的图像列表
照片列表是一个水平的ListView,它显示来自名为imagePaths的ListModel的图像。 在背景中,使用了一个半透明的黑色Rectangle。
ListModel {
id: imagePaths
}
ListView {
id: listView
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
height: 100
orientation: ListView.Horizontal
spacing: 10
model: imagePaths
delegate: Image {
required property string path
height: 100
source: path
fillMode: Image.PreserveAspectFit
}
Rectangle {
anchors.fill: parent
anchors.topMargin: -10
color: "black"
opacity: 0.5
}
}对于图像的拍摄,CaptureSession元素包含一组用于各种任务的子元素。 为了捕捉静态图片,使用了CaptureSession.imageCapture元素。 当调用captureToFile方法时,会拍摄一张图片并将其保存在用户的本地图片目录中,这将会导致CaptureSession.imageCapture发出imageSaved信号。
Button {
id: shotButton
width: parent.buttonWidth
height: parent.buttonHeight
text: qsTr("Take Photo")
onClicked: {
captureSession.imageCapture.captureToFile()
}
}在这种情况下,不需要显示预览图像,只需将生成的图像添加到屏幕底部的ListView即可。 如下例所示,保存图像的路径作为path参数随信号提供。
CaptureSession {
id: captureSession
videoOutput: output
camera: Camera {}
imageCapture: ImageCapture {
onImageSaved: function (id, path) {
imagePaths.append({"path": path})
listView.positionViewAtEnd()
}
}
}提示
要显示预览,请连接到imageCaptured信号并使用信号参数preview作为Image元素的source。信号参数id随imageCaptured和imageSaved一起发送,这个值是从capture方法返回的。 使用它,可以在整个周期中跟踪图像的捕获。 这样,可以先使用预览,然后将其替换为正确保存的图像。 然而,在示例中并不是这样做的。
# 切换相机
如果用户有多个摄像头,提供一种在这些摄像头之间切换的方法会很方便使用。 可以通过将MediaDevices元素与ListView结合使用来实现此目的。 在此例子中,将使用一个ComboBox组件:
MediaDevices {
id: mediaDevices
}
ComboBox {
id: cameraComboBox
width: parent.buttonWidth
height: parent.buttonHeight
model: mediaDevices.videoInputs
textRole: "description"
displayText: captureSession.camera.cameraDevice.description
onActivated: function (index) {
captureSession.camera.cameraDevice = cameraComboBox.currentValue
}
}ComboBox的model属性设置为MediaDevices的videoInputs属性,videoInputs属性包含可用视频输入的列表。 然后将控件的displayText设置为相机设备的描述(captureSession.camera.cameraDevice.description)。
最后,当用户切换视频输入时,cameraDevice会更新以反映该变化,即captureSession.camera.cameraDevice = cameraComboBox.currentValue。
# 回放
应用程序的最后一部分是实际播放。 这使用Timer元素和一些JavaScript函数驱动。 _imageIndex变量用于跟踪当前显示的图像。 显示到最后一张图像时,播放停止。 在示例中,root.state用于在播放序列时隐藏部分用户界面。
property int _imageIndex: -1
function startPlayback() {
root.state = "playing"
root.setImageIndex(0)
playTimer.start()
}
function setImageIndex(i) {
root._imageIndex = i
if (root._imageIndex >= 0 && root._imageIndex < imagePaths.count) {
image.source = imagePaths.get(root._imageIndex).path
} else {
image.source = ""
}
}
Timer {
id: playTimer
interval: 200
repeat: false
onTriggered: {
if (root._imageIndex + 1 < imagePaths.count) {
root.setImageIndex(root._imageIndex + 1)
playTimer.start()
} else {
root.setImageIndex(-1)
root.state = ""
}
}
}