Foto-Oberfläche
Eine QML-App für Touch-Geräte, die einen Repeater mit einem FolderListModel verwendet, um auf Inhalte in einem Ordner zuzugreifen, und ein PinchHandler, um Pinch-Gesten auf den abgerufenen Inhalten zu verarbeiten.

Photo Surface demonstriert, wie ein Repeater mit einem FolderListModel und einem FolderDialog verwendet wird, um auf Bilder aus einem vom Benutzer ausgewählten Ordner zuzugreifen. Das Beispiel zeigt auch, wie das Ziehen, Drehen und Zoomen innerhalb desselben Elements mithilfe von Qt Quick Input Handlers gehandhabt werden kann.
Der gesamte Anwendungscode ist in einer QML-Datei enthalten, photosurface.qml. Inline-JavaScript-Code platziert, dreht und skaliert Bilder auf der Fotooberfläche.
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorauszuführen, öffnen Sie den Modus Welcome und wählen Sie das Beispiel aus Examples. Weitere Informationen finden Sie unter Qt Creator: Tutorial: Erstellen und Ausführen.
Erstellen des Hauptfensters
Um das Hauptfenster für die Photo Surface-App zu erstellen, verwenden Sie den QML-Typ Window als Stammelement. Er richtet das Fenster automatisch für die Verwendung mit Qt Quick grafischen Typen:
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
Zugriff auf den Inhalt von Ordnern
Verwenden Sie einen Repeater QML-Typ zusammen mit FolderListModel, um die GIF-, JPG- und PNG-Bilder in einem Ordner anzuzeigen (obwohl main.cpp die Liste der unterstützten Bildtypen erweitern kann):
Repeater { model: FolderListModel { id: folderModel objectName: "folderModel" showDirs: false nameFilters: root.imageNameFilters }
Importieren Sie den Typ FolderListModel:
import Qt.labs.folderlistmodel
Ein FolderDialog ermöglicht es dem Benutzer, den Ordner auszuwählen, der die Bilder enthält:
FolderDialog { id: folderDialog title: qsTr("Choose a folder with some images") onAccepted: folderModel.folder = selectedFolder }
Um den FolderDialog-Typ zu verwenden, fügen Sie die folgende Import-Anweisung hinzu:
import QtQuick.Dialogs
Die Funktion folderDialog.open() öffnet den Dateidialog, wenn die anfängliche Diashow beendet ist, es sei denn, es wurde ein Ordnerpfad als Befehlszeilenargument angegeben:
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() }
Benutzer können auch auf das Symbol des Ordnerdialogs klicken, um ihn zu öffnen. Hier zeigt ein Image QML-Typ das Symbol an. Innerhalb des Typs Image ruft ein TapHandler mit dem Signalhandler onTapped die Funktion folderDialog.open() auf:
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() } }
Anzeige von Bildern auf der Fotooberfläche
Ein Rectangle wird als Delegierter für ein Repeater verwendet, um einen Rahmen für jedes Bild bereitzustellen, das FolderListModel im ausgewählten Ordner findet. Die JavaScript-Methoden Math() platzieren die Rahmen zufällig auf der Fotooberfläche, drehen sie in zufälligen Winkeln und skalieren die Bilder. Die Farbe des Rahmens zeigt den Zustand der Interaktion an:
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 }
Handhabung von Zieh- und Kneifgesten und der Maus
Ein DragHandler und ein PinchHandler in jedem Fotorahmen dienen zum Ziehen, Zoomen und Drehen:
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) } }
Da PinchHandler innerhalb des Rechtecks deklariert ist, ist die Eigenschaft PinchHandler.target implizit so eingestellt, dass Pinch-Gesten das Rechteck manipulieren. Die Rotationseigenschaften legen fest, dass die Rahmen in alle Winkel gedreht werden können, und die Skalierungseigenschaften legen fest, dass sie zwischen 0.1 und 10 skaliert werden können. Die Pinch-Geste funktioniert auch auf einem Touchscreen oder einem Multi-Touch-Touchpad. Durch das Transformieren des Rahmens wird sein Inhalt (das Bild) transformiert.
Die Eigenschaft DragHandler.target ist ebenfalls implizit festgelegt, so dass Sie ein Foto mit einem Finger auf einem Touchscreen oder Touchpad oder mit einer Maus ziehen können. Im Signalhandler onActiveChanged von DragHandler wird der ausgewählte Fotorahmen nach oben gezogen, indem der Wert der Eigenschaft z erhöht wird (während die gemeinsame Eigenschaft highestZ den größten bisher verwendeten Wert z enthält). Nach Beendigung des Ziehens beginnt eine Animation, die das Bild eine Weile in dieselbe Richtung bewegt, dann langsamer wird und schließlich zum Stillstand kommt. Wenn Sie ein Foto über den Rand der Oberfläche hinaus "schleudern", dehnt sich die Oberfläche aus, um die neue Position aufzunehmen. Sie können sich bewegen, um verschiedene Teile der Oberfläche über die ScrollView zu betrachten, die den Repeater und alle von ihm befüllten Fotorahmen enthält.
Da Sie zwei Fotos mit zwei Fingern über ihre DragHandler ziehen können und Sie auch ein PinchHandler mit zwei Fingern festhalten können und sich Fotosammlungen übereinander stapeln, müssen Sie grabPermissions so anpassen, dass PinchHandler Vorrang hat: Wenn die Geste des Festhaltens beginnt, lässt sie nicht zu, dass die DragHandler die Touchpoint-Griffe wieder übernehmen.
Um das Beispiel auf Computern ohne Touch-Geräte interaktiver zu machen, fügen Sie die HoverHandler, von der die obige border.color abhängt, und zwei WheelHandlers hinzu. Mit dem einen können Sie die Strg-Taste gedrückt halten und das Mausrad verwenden, um das Foto um den Mauszeiger zu drehen; mit dem anderen können Sie die Umschalttaste gedrückt halten und das Mausrad verwenden, um die Position unter dem Mauszeiger zu vergrößern oder zu verkleinern. In beiden Fällen wird das Foto auf die gleiche Weise angehoben, wie es auf DragHandler der Fall ist:
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 }
Quelldateien
Siehe auch QML-Anwendungen und Qt Quick Beispiele und 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.