フォトサーフェス
タッチデバイス用のQMLアプリで、リピータとFolderListModel を使ってフォルダ内のコンテンツにアクセスし、PinchHandler を使って取得したコンテンツのピンチジェスチャーを処理します。

Photo Surfaceは、FolderListModel とFolderDialog を持つRepeater を使用して、ユーザーが選択したフォルダから画像にアクセスする方法を示しています。この例では、Qt Quick 入力ハンドラを使用して、同じアイテム内でのドラッグ、回転、ピンチによるズームを処理する方法も示しています。
すべてのアプリコードは、1つのQMLファイル(photosurface.qml )に含まれています。インラインJavaScriptコードは、フォトサーフェス上に画像を配置、回転、拡大縮小します。
例の実行
からサンプルを実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Qt Creator:Tutorialを参照してください:ビルドと実行を参照してください。
メインウィンドウの作成
Photo Surfaceアプリのメインウィンドウを作成するには、Window QMLタイプをルートアイテムとして使用します。QMLタイプは自動的に Qt Quickグラフィカルタイプで使用するためのウィンドウが自動的にセットアップされます:
Window { id: root visible: true width: 1024; height: 600 color: "black" title: Application.displayName + " : " + folderModel.folder property real defaultSize: 200 property real surfaceViewportRatio: 1.5 property var imageNameFilters: ["*.png", "*.jpg", "*.gif"] // overridden in main.cpp
フォルダコンテンツへのアクセス
フォルダ内の GIF、JPG、PNG 画像を表示するには、FolderListModel とともにRepeater QML タイプを使用します(ただし、main.cpp ではサポートされる画像タイプのリストが拡張される場合があります):
Repeater { model: FolderListModel { id: folderModel objectName: "folderModel" showDirs: false nameFilters: root.imageNameFilters }
import Qt.labs.folderlistmodel
FolderDialog を使用すると、ユーザーは画像を含むフォルダを選択できます:
FolderDialog { id: folderDialog title: qsTr("Choose a folder with some images") onAccepted: folderModel.folder = selectedFolder }
FolderDialog タイプを使用するには、次の import 文を追加します:
import QtQuick.Dialogs
folderDialog.open() 関数は、コマンドライン引数としてフォルダパスが与えられていない限り、最初のスライドショーが終了したときにファイルダイアログを開きます:
Component.onDestruction: { folderIcon.visible = true const lastArg = Application.arguments.slice(-1)[0] const standardPicturesLocations = StandardPaths.standardLocations(StandardPaths.PicturesLocation) const hasValidPicturesLocation = standardPicturesLocations.length > 0 if (hasValidPicturesLocation) folderDialog.currentFolder = standardPicturesLocations[0] if (/.*hotosurface.*|--+/.test(lastArg)) { if (hasValidPicturesLocation) folderModel.folder = standardPicturesLocations[0] else folderDialog.open() }
ユーザーはフォルダダイアログのアイコンをクリックして開くこともできます。ここでは、ImageQML タイプがアイコンを表示しています。Imageタイプの内部では、onTapped シグナルハンドラを持つTapHandler がfolderDialog.open() 関数を呼び出します:
Image { id: folderIcon visible: false anchors.top: parent.top anchors.left: parent.left anchors.margins: 10 source: "resources/folder.png" TapHandler { onTapped: folderDialog.open() } HoverHandler { id: folderMouse } ToolTip.visible: folderMouse.hovered ToolTip.text: qsTr(`Open an image directory (${openShortcut.nativeText})`) ToolTip.delay: 1000 Shortcut { id: openShortcut sequence: StandardKey.Open onActivated: folderDialog.open() } }
フォトサーフェスに画像を表示する
Rectangle はRepeater のデリゲートとして使用され、FolderListModel が選択されたフォルダ内で見つけた各画像のフレームを提供します。JavaScriptのMath() メソッドは、写真表面にフレームをランダムに配置し、ランダムな角度で回転させ、画像を拡大縮小します。枠の色はインタラクションの状態を示す:
delegate: Rectangle { id: photoFrame required property date fileModified required property string fileName required property url fileUrl objectName: "frame-" + fileName width: image.width * (1 + 0.10 * image.height / image.width) height: image.height * 1.10 scale: root.defaultSize / Math.max(image.sourceSize.width, image.sourceSize.height) border.color: pinchHandler.active || dragHandler.active ? "darkturquoise" : mouse.hovered ? "darkseagreen" : "saddlebrown" border.width: 3 / scale antialiasing: true Component.onCompleted: { x = Math.random() * root.width - width / 2 y = Math.random() * root.height - height / 2 rotation = Math.random() * 13 - 6 } Image { id: image anchors.centerIn: parent fillMode: Image.PreserveAspectFit source: photoFrame.fileUrl antialiasing: true }
ドラッグとピンチのジェスチャー、およびマウスの処理
各フォトフレーム内のDragHandler とPinchHandler は、ドラッグ、ピンチズーム、回転を処理します:
PinchHandler { id: pinchHandler minimumRotation: -360 maximumRotation: 360 minimumScale: 0.1 maximumScale: 10 grabPermissions: PointerHandler.CanTakeOverFromAnything // and never gonna give it up onActiveChanged: if (active) photoFrame.z = ++flick.highestZ } DragHandler { id: dragHandler onActiveChanged: { if (active) photoFrame.z = ++flick.highestZ else anim.restart(centroid.velocity) } }
PinchHandler は Rectangle の内部で宣言されているため、PinchHandler.target プロパティが暗黙的に設定され、ピンチジェスチャーが Rectangle を操作できるようになっています。回転プロパティは、フレームをあらゆる角度に回転できることを指定し、スケールプロパティは、フレームを0.1 と10 の間で拡大縮小できることを指定します。ピンチ・ジェスチャーは、タッチスクリーンやマルチタッチ・タッチパッドでも同様に機能します。フレームを変形すると、そのコンテンツ(イメージ)が変形します。
DragHandler.target プロパティも暗黙のうちに設定されているため、タッチスクリーンやタッチパッド上で、またはマウスを使って、指一本で写真をドラッグすることができます。DragHandler'のonActiveChanged シグナルハンドラでは、選択されたフォトフレームは、そのz プロパティの値を増加させることで、上部に上がります(一方、共有されたhighestZ プロパティには、これまでに使用された最大のz 値が保持されます)。ドラッグが終わると、少しの間同じ方向に動き続けるアニメーションが始まり、減速して停止する。写真をサーフェスの端から「はみ出させる」と、サーフェスは新しい位置に合わせて広がります。リピーターと、リピーターが入力するすべてのフォトフレームを含むScrollView 、サーフェスのさまざまな部分を見るために移動することができます。
DragHandlers を介して2本の指で2枚の写真をドラッグすることができ、2本の指で1つのPinchHandler をピンチすることもできます。写真のコレクションは互いに重なり合う傾向があるため、PinchHandler が優先されるようにgrabPermissions を調整する必要があります。ピンチジェスチャーが始まると、DragHandlers が再びタッチポイントのグラブを引き継ぐことを許可しません。
タッチデバイスのないコンピュータでこの例をよりインタラクティブにするには、上記のborder.colorが依存するHoverHandler 、2つのWheelHandlers 。もう1つは、Shiftキーを押しながらマウスホイールを使って、カーソルのある位置を拡大・縮小するものです。どちらも、上のDragHandler と同じように、写真を上昇させることができます:
HoverHandler { id: mouse } WheelHandler { acceptedModifiers: Qt.ControlModifier property: "rotation" onActiveChanged: if (active) photoFrame.z = ++flick.highestZ } WheelHandler { acceptedModifiers: Qt.ShiftModifier property: "scale" onActiveChanged: if (active) photoFrame.z = ++flick.highestZ }
ソースファイル
QML ApplicationsおよびQt Quick Examples and Tutorialsも参照して ください。
© 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.