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

„Photo Surface“ veranschaulicht, wie man mit einem „ Repeater “, einem „ FolderListModel “ und einem „ FolderDialog “ auf Bilder aus einem vom Benutzer ausgewählten Ordner zugreift. Das Beispiel zeigt außerdem, wie man das Ziehen, Drehen und Zoomen per Pinch-Geste innerhalb desselben Elements mithilfe von „Qt Quick “-Eingabehandlern handhabt.
Der gesamte App-Code ist in einer einzigen QML-Datei enthalten: photosurface.qml. Inline-JavaScript-Code platziert, dreht und skaliert Bilder auf der Fotooberfläche.
Ausführen des Beispiels
Sie können das Beispiel wie folgt ausführen:
- Qt Creator
Öffnen Sie den Modus „ Welcome “ und wählen Sie das Beispiel unter „ Examples “ aus. Weitere Informationen finden Sie unter Qt Creator: Tutorial: Erstellen und Ausführen.
- Qt Extension for Visual Studio Code
Führen Sie den Befehl „ Qt: Open Qt examples “ über „ Command Palette “ aus und wählen Sie das Beispiel aus der Liste aus. Weitere Informationen finden Sie unter Qt Extension for Visual Studio Code: Tutorial: Erstellen und Ausführen.
Erstellen des Hauptfensters
Um das Hauptfenster für die App „Photo Surface“ zu erstellen, verwenden Sie den QML-Typ „ Window “ als Stammelement. Dieser richtet das Fenster automatisch für die Verwendung mit Qt Quick grafische 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.cppAuf den Inhalt eines Ordners zugreifen
Verwenden Sie den QML-Typ „ Repeater “ zusammen mit der „ FolderListModel “, um die in einem Ordner befindlichen GIF-, JPG- und PNG-Bilder anzuzeigen (wobei „main.cpp“ die Liste der unterstützten Bildformate möglicherweise erweitert):
Repeater {
model: FolderListModel {
id: folderModel
objectName: "folderModel"
showDirs: false
nameFilters: root.imageNameFilters
}Importieren Sie den Typ „ FolderListModel “:
import Qt.labs.folderlistmodelEin „FolderDialog“ ermöglicht es Benutzern, 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 Typ „FolderDialog“ zu verwenden, fügen Sie die folgende Importanweisung hinzu:
import QtQuick.DialogsDie Funktion „ folderDialog.open() “ öffnet den Dateidialog, sobald die erste Diashow beendet ist, sofern kein Ordnerpfad als Befehlszeilenargument angegeben wurde:
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 den Ordnerdialog auch durch Klicken auf das entsprechende Symbol öffnen. Hier wird das Symbol durch einen „Image“-QML-Typ dargestellt. Innerhalb des „Image“-Typs ruft ein „ TapHandler “ mit dem Signal-Handler „ 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()
}
}Anzeigen von Bildern auf der „Photo“-Oberfläche
Ein „ Rectangle “ wird als Delegat für ein „ Repeater “ verwendet, um für jedes Bild, das „ FolderListModel “ im ausgewählten Ordner findet, einen Rahmen bereitzustellen. JavaScript-Methoden von „ Math() “ platzieren die Rahmen zufällig auf der Fotooberfläche, drehen sie in zufälligen Winkeln und skalieren die Bilder. Die Rahmenfarbe zeigt den Interaktionsstatus 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
}Verarbeitung von Zieh- und Pinch-Gesten sowie der Maus
Ein ` DragHandler ` und ein ` PinchHandler ` in jedem Fotorahmen verarbeiten Zieh-, Zoom- und Drehgesten:
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 der „ PinchHandler “ innerhalb des „Rectangle“ deklariert ist, wird die Eigenschaft „ PinchHandler.target “ implizit so festgelegt, dass Pinch-Gesten das „Rectangle“ 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 auf einem Touchscreen oder einem Multi-Touch-Touchpad gleichermaßen gut. Durch die Transformation des Rahmens wird auch dessen Inhalt (das Bild) transformiert.
Die Eigenschaft „ DragHandler.target “ ist ebenfalls implizit festgelegt, sodass Sie ein Foto mit einem Finger auf einem Touchscreen oder Touchpad oder mit einer Maus ziehen können. Im Signal-Handler „ onActiveChanged “ des „ DragHandler “ wird der ausgewählte Fotorahmen nach vorne geholt, indem der Wert seiner Eigenschaft „ z “ erhöht wird (während die gemeinsam genutzte Eigenschaft „ highestZ “ den größten bisher verwendeten Wert für „ z “ enthält). Wenn das Ziehen endet, beginnt eine Animation, die den Fotorahmen noch eine Weile in derselben Richtung weiterbewegt, bis er langsamer wird und zum Stillstand kommt. Wenn Sie ein Foto über den Rand der Oberfläche hinaus „schleudern“, erweitert sich die Oberfläche, um die neue Position aufzunehmen. Sie können sich frei bewegen, um verschiedene Bereiche der Oberfläche über den „ ScrollView “ zu betrachten, der den „Repeater“ und alle von ihm gefüllten Fotorahmen enthält.
Da Sie zwei Fotos mit zwei Fingern über deren „DragHandler“ ziehen und zudem einen „ PinchHandler “ mit zwei Fingern zusammenziehen können und sich Fotosammlungen dazu neigen, sich übereinander zu stapeln, müssen Sie „ grabPermissions “ so anpassen, dass der „ PinchHandler “ Vorrang hat: Wenn die Zusammenzugsgeste beginnt, verhindert er, dass die „DragHandler“ die Berührungspunkte wieder übernehmen.
Um das Beispiel auf Computern ohne Touch-Geräte interaktiver zu gestalten, fügen Sie den „ HoverHandler “ hinzu, von dem die oben genannte „border.color“ abhängt, sowie zwei „ WheelHandlers “. Mit dem einen können Sie die Strg-Taste gedrückt halten und das Mausrad verwenden, um das Foto um den Mauszeiger herum 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. Beide heben das Foto auf dieselbe Weise an wie der oben genannte ` 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
}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.