このページでは

QML カメラアプリケーション

このQt Quick ベースのアプリケーションは、APIを使用して静止画や動画を撮影する方法を示しています。

横向き表示のカメラアプリで、ライブプレビューと撮影操作が表示されている

この例では、QML を通じてカメラ機能にアクセスする方法を示しています。設定の変更や、静止画・動画のキャプチャ方法についても説明しています。

例の動作確認

以下の手順でサンプルを実行できます。

アプリケーションの構造

この例の 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 に示されているように、stillControls およびvideoControls オブジェクトは、いずれもこのItemのstate およびbuttonsWidth プロパティにバインドされています:

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.qml で実装されているZoomControlタイプは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 で定義されており、これによりスイッチを介してフラッシュモードの選択や懐中電灯機能の切り替えが可能になります。ズームコントロールと同様に、これらのスイッチは、アクティブなデバイスがこれらの機能をサポートしている場合にのみ、プレビューウィンドウの上に表示されます。

ここでは、これらの機能がサポートされているかどうかを確認します:

required property Camera camera

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

ここでは、flashModeControl のスイッチを実装します。このスイッチは、Cameraデバイスを直接制御します。

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
}

トーチ制御も同様の方法で実装されます。

サンプルプロジェクト @ 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.