フォトサーフェス
リピータとFolderListModel を使ってフォルダ内のコンテンツにアクセスし、PinchHandler を使って取得したコンテンツのピンチジェスチャーを処理する、タッチデバイス用の QML アプリです。
Photo Surfaceは、FolderListModel とFolderDialog を持つRepeater を使用して、ユーザーが選択したフォルダから画像にアクセスする方法と、Qt Quick Input Handlers を使用して、同じアイテム内でのドラッグ、回転、ピンチによるズームを処理する方法を示します。
すべてのアプリコードは、1つのQMLファイル(photosurface.qml
)に含まれています。インラインJavaScriptコードは、写真表面上の画像を配置、回転、拡大縮小するために使用されます。
サンプルを実行する
Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。
メインウィンドウの作成
Photo Surfaceアプリのメインウィンドウを作成するために、Window 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
フォルダコンテンツへのアクセス
Repeater QML型とFolderListModel QML型を使って、少なくともフォルダ内のGIF、JPG、PNG画像を表示します(ただし、main.cppはサポートする画像タイプのリストを拡張することがあります):
Repeater { model: FolderListModel { id: folderModel objectName: "folderModel" showDirs: false nameFilters: root.imageNameFilters }
FolderListModel 型を使用するには、インポートする必要があります:
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() } }
フォトサーフェスに画像を表示する
Repeater のデリゲートとしてRectangle を使用し、FolderListModel が選択されたフォルダ内で見つけた各画像のフレームを提供します。JavaScriptのMath()
メソッドを使用して、写真サーフェス上にフレームをランダムに配置し、ランダムな角度で回転させ、画像を拡大縮小します。枠の色はインタラクションの状態を示している:
delegate: Rectangle { required property date fileModified required property string fileName required property url fileUrl id: photoFrame 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 。もうひとつは、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アプリケーションも参照してください 。
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。