aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick/pointerhandlers
diff options
context:
space:
mode:
Diffstat (limited to 'examples/quick/pointerhandlers')
-rw-r--r--examples/quick/pointerhandlers/CMakeLists.txt43
-rw-r--r--examples/quick/pointerhandlers/components/CorkPanel.qml118
-rw-r--r--examples/quick/pointerhandlers/components/FlashAnimation.qml8
-rw-r--r--examples/quick/pointerhandlers/components/MouseFeedbackSprite.qml13
-rw-r--r--examples/quick/pointerhandlers/components/QuadPieMenu.qml7
-rw-r--r--examples/quick/pointerhandlers/components/ScrollBar.qml4
-rw-r--r--examples/quick/pointerhandlers/components/images/cork.jpgbin0 -> 149337 bytes
-rw-r--r--examples/quick/pointerhandlers/components/images/note-yellow.pngbin0 -> 54283 bytes
-rw-r--r--examples/quick/pointerhandlers/components/images/tack.pngbin0 -> 7282 bytes
-rw-r--r--examples/quick/pointerhandlers/corkboards.qml51
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fakeflickable.jpgbin0 -> 104984 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webpbin0 -> 48514 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpgbin0 -> 81973 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webpbin0 -> 424394 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webpbin0 -> 185554 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webpbin0 -> 620084 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webpbin0 -> 40846 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webpbin0 -> 999018 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webpbin0 -> 286790 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webpbin0 -> 155468 bytes
-rw-r--r--examples/quick/pointerhandlers/doc/src/pointerhandlers.qdoc171
-rw-r--r--examples/quick/pointerhandlers/images/blur-circle.pngbin0 -> 4279 bytes
-rw-r--r--examples/quick/pointerhandlers/multiflame.qml69
-rw-r--r--examples/quick/pointerhandlers/pointerhandlers.qml6
-rw-r--r--examples/quick/pointerhandlers/qml.qrc9
-rw-r--r--examples/quick/pointerhandlers/tapHandler.qml34
26 files changed, 492 insertions, 41 deletions
diff --git a/examples/quick/pointerhandlers/CMakeLists.txt b/examples/quick/pointerhandlers/CMakeLists.txt
index d0fdd89eae..a8b3cbe3d0 100644
--- a/examples/quick/pointerhandlers/CMakeLists.txt
+++ b/examples/quick/pointerhandlers/CMakeLists.txt
@@ -1,39 +1,33 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(pointerhandlers LANGUAGES CXX)
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/pointerhandlers")
-
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick Svg)
-qt_standard_project_setup()
+qt_standard_project_setup(REQUIRES 6.5)
add_subdirectory("../shared" "shared")
qt_add_executable(pointerhandlersexample WIN32 MACOSX_BUNDLE main.cpp)
target_link_libraries(pointerhandlersexample PRIVATE
- Qt::Core
- Qt::Gui
- Qt::Qml
- Qt::Quick
- Qt::Svg
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Qml
+ Qt6::Quick
+ Qt6::Svg
)
add_dependencies(pointerhandlersexample pointerhandlers_shared)
qt_add_qml_module(pointerhandlersexample
URI pointerhandlers
- AUTO_RESOURCE_PREFIX
QML_FILES
"components/Button.qml"
"components/CheckBox.qml"
+ "components/CorkPanel.qml"
"components/FakeFlickable.qml"
"components/FlashAnimation.qml"
"components/LeftDrawer.qml"
@@ -43,12 +37,14 @@ qt_add_qml_module(pointerhandlersexample
"components/ScrollBar.qml"
"components/Slider.qml"
"components/TouchpointFeedbackSprite.qml"
+ "corkboards.qml"
"fakeFlickable.qml"
"flingAnimation.qml"
"joystick.qml"
"map.qml"
"mixer.qml"
"multibuttons.qml"
+ "multiflame.qml"
"pieMenu.qml"
"pinchHandler.qml"
"pointerhandlers.qml"
@@ -58,6 +54,7 @@ qt_add_qml_module(pointerhandlersexample
"tapHandler.qml"
RESOURCES
"components/images/checkmark.png"
+ "components/images/cork.jpg"
"components/images/fingersprite.png"
"components/images/mixer-knob.png"
"components/images/mouse.png"
@@ -65,8 +62,11 @@ qt_add_qml_module(pointerhandlersexample
"components/images/mouse_middle.png"
"components/images/mouse_right.png"
"components/images/mouse_wheel_ridges.png"
+ "components/images/note-yellow.png"
+ "components/images/tack.png"
"images/arrowhead.png"
"images/balloon.png"
+ "images/blur-circle.png"
"images/cursor-airbrush.png"
"images/cursor-eraser.png"
"images/cursor-felt-marker.png"
@@ -80,9 +80,16 @@ qt_add_qml_module(pointerhandlersexample
)
install(TARGETS pointerhandlersexample
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
-bundle_shared(pointerhandlersexample)
+qt_generate_deploy_qml_app_script(
+ TARGET pointerhandlersexample
+ OUTPUT_SCRIPT deploy_script
+ MACOS_BUNDLE_POST_BUILD
+ NO_UNSUPPORTED_PLATFORM_ERROR
+ DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM
+)
+install(SCRIPT ${deploy_script})
diff --git a/examples/quick/pointerhandlers/components/CorkPanel.qml b/examples/quick/pointerhandlers/components/CorkPanel.qml
new file mode 100644
index 0000000000..4aec2b5c7c
--- /dev/null
+++ b/examples/quick/pointerhandlers/components/CorkPanel.qml
@@ -0,0 +1,118 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Image {
+ id: corkPanel
+ source: Qt.resolvedUrl("images/cork.jpg")
+ width: ListView.view.width
+ height: ListView.view.height
+ fillMode: Image.PreserveAspectCrop
+
+ required property string name
+ required property var notes
+
+ TapHandler {
+ objectName: corkPanel.name
+ onTapped: corkPanel.Window.activeFocusItem.focus = false
+ }
+
+ Text {
+ text: corkPanel.name
+ x: 15
+ y: 8
+ height: 40
+ width: 370
+ font.pixelSize: 18
+ font.bold: true
+ color: "white"
+ style: Text.Outline
+ styleColor: "black"
+ wrapMode: Text.Wrap
+ }
+
+ Repeater {
+ model: corkPanel.notes
+ Item {
+ id: fulcrum
+
+ x: 100 + Math.random() * (corkPanel.width - 0.5 * paper.width)
+ y: 50 + Math.random() * (corkPanel.height - 0.5 * paper.height)
+
+ Item {
+ id: note
+ scale: 0.7
+
+ Image {
+ id: paper
+ x: 8 + -width * 0.6 / 2
+ y: -20
+ source: "images/note-yellow.png"
+ scale: 0.6
+ transformOrigin: Item.TopLeft
+ antialiasing: true
+
+ DragHandler {
+ target: fulcrum
+ xAxis.minimum: 100
+ xAxis.maximum: corkPanel.width - 80
+ yAxis.minimum: 0
+ yAxis.maximum: corkPanel.height - 80
+ }
+ }
+
+ TextEdit {
+ id: text
+ x: -104
+ y: 36
+ width: 215
+ height: 24
+ font.pixelSize: 24
+ readOnly: false
+ selectByMouse: activeFocus
+ rotation: -8
+ text: noteText
+ wrapMode: Text.Wrap
+ }
+
+ rotation: -flickable.horizontalVelocity / 100
+ Behavior on rotation {
+ SpringAnimation {
+ spring: 2.0
+ damping: 0.15
+ }
+ }
+ }
+
+ Image {
+ x: -width / 2
+ y: -height * 0.5 / 2
+ source: "images/tack.png"
+ scale: 0.7
+ transformOrigin: Item.TopLeft
+ }
+
+ states: State {
+ name: "pressed"
+ when: text.activeFocus
+ PropertyChanges {
+ target: note
+ rotation: 8
+ scale: 1
+ }
+ PropertyChanges {
+ target: fulcrum
+ z: 8
+ }
+ }
+
+ transitions: Transition {
+ NumberAnimation {
+ properties: "rotation,scale"
+ duration: 200
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/pointerhandlers/components/FlashAnimation.qml b/examples/quick/pointerhandlers/components/FlashAnimation.qml
index e369282470..bdbcaecdfa 100644
--- a/examples/quick/pointerhandlers/components/FlashAnimation.qml
+++ b/examples/quick/pointerhandlers/components/FlashAnimation.qml
@@ -6,15 +6,9 @@ import QtQuick
SequentialAnimation {
id: tapFlash
running: false
+ loops: 3
PropertyAction { value: false }
PauseAnimation { duration: 100 }
PropertyAction { value: true }
PauseAnimation { duration: 100 }
- PropertyAction { value: false }
- PauseAnimation { duration: 100 }
- PropertyAction { value: true }
- PauseAnimation { duration: 100 }
- PropertyAction { value: false }
- PauseAnimation { duration: 100 }
- PropertyAction { value: true }
}
diff --git a/examples/quick/pointerhandlers/components/MouseFeedbackSprite.qml b/examples/quick/pointerhandlers/components/MouseFeedbackSprite.qml
index 1de4de8e48..57c58d826f 100644
--- a/examples/quick/pointerhandlers/components/MouseFeedbackSprite.qml
+++ b/examples/quick/pointerhandlers/components/MouseFeedbackSprite.qml
@@ -10,22 +10,27 @@ HoverHandler {
target: Image {
objectName: "mouse sprite"
source: "images/mouse.png"
- opacity: (handler.point.pressedButtons || wheelAnimationTimer.running) ? 1 : 0
+ opacity: (phandler.point.pressedButtons || wheelAnimationTimer.running) ? 1 : 0
x: handler.point.position.x - width / 2
y: handler.point.position.y - height / 2
parent: handler.parent
Image {
source: "images/mouse_left.png"
- visible: handler.point.pressedButtons & Qt.LeftButton
+ visible: phandler.point.pressedButtons & Qt.LeftButton
}
Image {
source: "images/mouse_middle.png"
- visible: handler.point.pressedButtons & Qt.MiddleButton
+ visible: phandler.point.pressedButtons & Qt.MiddleButton
}
Image {
source: "images/mouse_right.png"
- visible: handler.point.pressedButtons & Qt.RightButton
+ visible: phandler.point.pressedButtons & Qt.RightButton
}
+ PointHandler {
+ id: phandler
+ acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
+ }
+
WheelHandler {
blocking: false
onWheel: (event)=> {
diff --git a/examples/quick/pointerhandlers/components/QuadPieMenu.qml b/examples/quick/pointerhandlers/components/QuadPieMenu.qml
index 9c2364fea2..eae268eccb 100644
--- a/examples/quick/pointerhandlers/components/QuadPieMenu.qml
+++ b/examples/quick/pointerhandlers/components/QuadPieMenu.qml
@@ -9,6 +9,7 @@ TapHandler {
signal triggered(string text)
id: menuTap
+ acceptedButtons: Qt.RightButton
gesturePolicy: TapHandler.DragWithinBounds
onPressedChanged: if (pressed) {
impl.x = point.position.x - impl.width / 2
@@ -22,7 +23,10 @@ TapHandler {
parent: menuTap.parent
width: 100
height: 100
- scale: Math.min(1, Math.max(0, menuTap.timeHeld * 4))
+ // with touchscreen or stylus, long-press slowly expands the menu to size
+ // with mouse or touchpad right-click, it opens instantly
+ scale: menuTap.point.device.pointerType === PointerDevice.Generic ?
+ 1 : Math.min(1, Math.max(0, menuTap.timeHeld * 4))
opacity: scale * 2
visible: menuTap.pressed
property Shape highlightedShape: null
@@ -35,6 +39,7 @@ TapHandler {
width: 100
height: 100
containsMode: Shape.FillContains
+ preferredRendererType: Shape.CurveRenderer
property bool highlighted: menuTap.pressed &&
shape.contains(shape.mapFromItem(menuTap.parent, menuTap.point.position))
diff --git a/examples/quick/pointerhandlers/components/ScrollBar.qml b/examples/quick/pointerhandlers/components/ScrollBar.qml
index d78ee56140..6b13c03305 100644
--- a/examples/quick/pointerhandlers/components/ScrollBar.qml
+++ b/examples/quick/pointerhandlers/components/ScrollBar.qml
@@ -70,7 +70,7 @@ Rectangle {
PropertyChanges {
knob {
max: root.width - knob.width
- scrolledX: Math.min(max, Math.max(0, max * flick.contentX / (flick.width - flick.contentWidth)))
+ scrolledX: Math.min(knob.max, Math.max(0, knob.max * flick.contentX / (flick.width - flick.contentWidth)))
scrolledY: 1
scrollDistance: flick.width - flick.contentWidth
width: flick.width * (flick.width / flick.contentWidth) - (height - anchors.margins) * 2
@@ -91,7 +91,7 @@ Rectangle {
knob {
max: root.height - knob.height
scrolledX: 1
- scrolledY: Math.min(max, Math.max(0, max * flick.contentY / (flick.height - flick.contentHeight)))
+ scrolledY: Math.min(knob.max, Math.max(0, knob.max * flick.contentY / (flick.height - flick.contentHeight)))
scrollDistance: flick.height - flick.contentHeight
width: root.width - 2
height: root.width - 2
diff --git a/examples/quick/pointerhandlers/components/images/cork.jpg b/examples/quick/pointerhandlers/components/images/cork.jpg
new file mode 100644
index 0000000000..160bc002bf
--- /dev/null
+++ b/examples/quick/pointerhandlers/components/images/cork.jpg
Binary files differ
diff --git a/examples/quick/pointerhandlers/components/images/note-yellow.png b/examples/quick/pointerhandlers/components/images/note-yellow.png
new file mode 100644
index 0000000000..3195952ad2
--- /dev/null
+++ b/examples/quick/pointerhandlers/components/images/note-yellow.png
Binary files differ
diff --git a/examples/quick/pointerhandlers/components/images/tack.png b/examples/quick/pointerhandlers/components/images/tack.png
new file mode 100644
index 0000000000..cef2d1cd23
--- /dev/null
+++ b/examples/quick/pointerhandlers/components/images/tack.png
Binary files differ
diff --git a/examples/quick/pointerhandlers/corkboards.qml b/examples/quick/pointerhandlers/corkboards.qml
new file mode 100644
index 0000000000..76928f1b8c
--- /dev/null
+++ b/examples/quick/pointerhandlers/corkboards.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import "components"
+
+Rectangle {
+ width: 320; height: 480
+ color: "#464646"
+
+ ListModel {
+ id: list
+
+ ListElement {
+ name: "Panel One"
+ notes: [
+ ListElement { noteText: "Tap to edit" },
+ ListElement { noteText: "Drag to move" },
+ ListElement { noteText: "Flick to scroll" }
+ ]
+ }
+
+ ListElement {
+ name: "Panel Two"
+ notes: [
+ ListElement { noteText: "Note One" },
+ ListElement { noteText: "Note Two" }
+ ]
+ }
+
+ ListElement {
+ name: "Panel Three"
+ notes: [
+ ListElement { noteText: "Note Three" }
+ ]
+ }
+ }
+
+ ListView {
+ id: flickable
+
+ anchors.fill: parent
+ focus: true
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ orientation: ListView.Horizontal
+ snapMode: ListView.SnapOneItem
+ model: list
+ delegate: CorkPanel { objectName: name }
+ }
+}
+
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fakeflickable.jpg b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fakeflickable.jpg
new file mode 100644
index 0000000000..5149665a07
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fakeflickable.jpg
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp
new file mode 100644
index 0000000000..4b8794971e
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg
new file mode 100644
index 0000000000..c9d167b1e7
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp
new file mode 100644
index 0000000000..b96b0cf90a
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp
new file mode 100644
index 0000000000..f263458d12
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp
new file mode 100644
index 0000000000..1d13805c64
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp
new file mode 100644
index 0000000000..cc5ca5d394
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp
new file mode 100644
index 0000000000..89f61251ab
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp
new file mode 100644
index 0000000000..1a0ac33d0c
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp
new file mode 100644
index 0000000000..162e97ea15
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp
Binary files differ
diff --git a/examples/quick/pointerhandlers/doc/src/pointerhandlers.qdoc b/examples/quick/pointerhandlers/doc/src/pointerhandlers.qdoc
new file mode 100644
index 0000000000..d9f2e5f1cc
--- /dev/null
+++ b/examples/quick/pointerhandlers/doc/src/pointerhandlers.qdoc
@@ -0,0 +1,171 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example pointerhandlers
+ \title Qt Quick Examples - Pointer Handlers
+ \ingroup qtquickexamples
+ \examplecategory {User Interface Components}
+ \meta tags {quick, input handlers}
+ \brief Shows how to use \l {Qt Quick Input Handlers} in interactive components.
+
+ \l {Qt Quick Controls} contains pre-built components that are sufficient
+ for many kinds of user interfaces; but you may sometimes find a need to
+ write such components "from scratch". In that case, you will need to make
+ substantial use of Pointer Handlers. This is a collection of small examples
+ that show how to implement some common and less-common interaction patterns.
+
+ If you build the example as an executable, you can choose pages from a
+ top-level ListView. The \c TouchpointFeedbackSprite and \c MouseFeedbackSprite
+ components show how to use PointHandler to provide feedback about what the
+ user is doing with the pointing devices: these components are always
+ visible throughout the example, and do not interfere with interaction
+ anywhere else. These components are handy for reuse if you ever need to do
+ a video or live demonstration of a user interface.
+
+ Alternatively, some of the individual QML files can be run on the command
+ line with the \l {QML Runtime Tool}{qml tool}, as a quick reminder to see
+ how a particular kind of component can be built.
+
+ \section1 TapHandler
+
+ \image pointerhandlers-example-taphandler.webp
+
+ The "tap" page shows how to detect touchscreen taps, long-presses, and
+ mouse clicks with different buttons. You can also try out the different
+ \l {TapHandler::}{gesturePolicy} values.
+
+ \section2 Multi-tap Buttons
+
+ On this page are three custom \c Button components, with different
+ \l {TapHandler::}{gesturePolicy} values: one button requires you
+ to keep your finger or mouse within the button during the whole time
+ from press to release; one will execute even if you drag outside
+ the button and then drag back in before releasing; and one will
+ exit its pressed state if you drag a little past the
+ \l {QStyleHints::startDragDistance}{system-wide drag threshold}.
+ If you try this example on a touchscreen, you should be able to interact
+ with all three buttons at the same time with different fingers.
+
+ \image pointerhandlers-example-multibutton.webp
+
+ \section2 Pie Menu
+
+ This page shows how to write a touchscreen-friendly pie menu that animates
+ into view when activated by a long-press. You can select a menu item by
+ dragging from the center position onto one of the sectors and releasing. If
+ you drag outside the menu, or release in the middle of the menu, nothing is
+ selected. If you drag outside the grey viewport, the menu is cancelled.
+
+ \image pointerhandlers-example-piemenu.webp
+
+ \section1 PointHandler
+
+ On the "single point handler" page, PointHandler provides feedback from
+ some of the properties that can be found in \l SinglePointHandler::point
+ and \l handlerPoint::device. If you have built the example as
+ an executable, you will see this feedback at the same time as the feedback
+ from the PointHandlers in the main pointerhandlers.qml file.
+
+ \image pointerhandlers-example-pointhandler.webp
+
+ The "tablet canvas" page uses PointHandler to uniquely detect different
+ \l {QPointingDevice::PointerType}{types of pointing devices}, so that if
+ you have a drawing tablet connected to your computer, you can draw on the
+ Canvas item with different types of stylus: pen, airbrush or marker. You
+ can "erase" strokes with the stylus eraser (done here by drawing on top
+ with the background color). Several \l {HoverHandler}{HoverHandlers}
+ provide feedback about which type of stylus or eraser is detected.
+
+ \section1 HoverHandler
+
+ The "hover sidebar" page shows how to detect when the mouse is hovering a
+ button component and its container at the same time. The propagation can be
+ disabled by setting the \l HoverHandler::blocking property. You can try out
+ all combinations of HoverHandler and MouseArea here, to compare how they
+ handle hover detection. And one more HoverHandler is used to show the
+ current mouse position in scene coordinates.
+
+ You can also verify that the HoverHandler on the animated "platform"
+ is hovered whenever it slides under the mouse cursor.
+
+ \section1 DragHandler
+
+ The "joystick" page simply has a \l DragHandler dragging an \l Image.
+ A \l State with \l AnchorChanges unlocks the \l anchors so that dragging is
+ possible; and an \l AnchorAnimation animates the knob's return to the
+ center position when released.
+
+ \image pointerhandlers-example-joystick.jpg
+
+ The "fling animation" page demonstrates one use of the
+ DragHandler::centroid::velocity property, which simply makes the value from
+ QEventPoint::velocity() available in QML. The \c MomentumAnimation component
+ that is used in this example shows one way to simulate phyics (momentum and
+ friction) without resorting to heavier solutions.
+
+ \image pointerhandlers-example-fling.webp
+
+ \section1 PinchHandler
+
+ The "pinch" page demonstrates multiple PinchHandlers: some require two
+ fingers and some require three, to perform the usual scaling, rotation and
+ translation, with constraints managed via PinchHandler's axis min and max
+ properties. One of the PinchHandler instances is used to manipulate
+ different \l Rectangle properties rather than position, scale and rotation.
+ Various PinchHandler properties are bound in various ways. You should be
+ able to manipulate each instance uniquely. Some items also have
+ DragHandlers and TapHandlers.
+
+ \image pointerhandlers-example-pinchhandler.webp
+
+ \section1 Interoperability
+
+ \section2 Sliders
+
+ The "mixer" page demonstrates the use of multiple handlers inside a
+ ListView delegate. You can interact with multiple \c Slider components
+ simultaneously, and you can flick the ListView sideways.
+
+ \list
+ \li A DragHandler allows you to start dragging anywhere along the "track"
+ where the slider knob can slide. Because the default \l{DragHandler::}{snapMode}
+ is \c DragHandler.SnapAuto, the knob will \e snap into a position centered
+ under the mouse or touchpoint after you have dragged past the
+ \l {QStyleHints::startDragDistance}{system-wide drag threshold}.
+
+ \li A WheelHandler directly adjusts the \c y property of the knob \l Image.
+
+ \li A BoundaryRule prevents either the DragHandler or the WheelHandler from
+ dragging the knob too far.
+
+ \li A TapHandler provides one more gesture than a typical \c Slider component
+ would have: you can tap on the knob.
+ \endlist
+
+ \image pointerhandlers-example-mixer.webp
+
+ \section2 Map
+
+ The "map" page demonstrates dragging, transformation and re-scaling an
+ \l {Qt SVG}{SVG} \l Image. You should be able to zoom into a particular
+ location on the map; and if the zoom level is changed substantially,
+ \l Image::sourceSize is changed to request the SVG to be re-rendered at a
+ different resolution. Dragging vertically with two fingers activates a
+ DragHandler that manipulates a \l Rotation transform to tilt the map.
+
+ \image pointerhandlers-example-map.webp
+
+ \section2 Fake Flickable
+
+ The "fake Flickable" page contains an attempt to reproduce much of the
+ functionality of \l Flickable using discrete pointer handlers and
+ animations. Flickable is a complex component, but here you can see one way
+ of separating the individual behaviors that it provides, in case you would
+ like to have only part of the functionality without the complexity.
+
+ There's also a slide-out "drawer" component holding a few more
+ pointer-handler-powered controls.
+
+ \image pointerhandlers-example-fakeflickable.jpg
+*/
diff --git a/examples/quick/pointerhandlers/images/blur-circle.png b/examples/quick/pointerhandlers/images/blur-circle.png
new file mode 100644
index 0000000000..1b03cd0b2c
--- /dev/null
+++ b/examples/quick/pointerhandlers/images/blur-circle.png
Binary files differ
diff --git a/examples/quick/pointerhandlers/multiflame.qml b/examples/quick/pointerhandlers/multiflame.qml
new file mode 100644
index 0000000000..7793e52ad6
--- /dev/null
+++ b/examples/quick/pointerhandlers/multiflame.qml
@@ -0,0 +1,69 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Particles
+
+Rectangle {
+ id: root
+ width: 360
+ height: 480
+ color: "black"
+
+ component ColoredEmitter: Emitter {
+ id: emitter
+ property string color
+ group: color
+ velocityFromMovement: 10
+ emitRate: 80
+ lifeSpan: 1500
+ velocity: PointDirection {
+ y: -90
+ yVariation: 50
+ }
+ acceleration: PointDirection {
+ xVariation: 100
+ yVariation: 90
+ }
+ size: 51
+ sizeVariation: 53
+ endSize: 64
+ enabled: handler.active
+ x: handler.point.position.x
+ y: handler.point.position.y
+
+ PointHandler {
+ id: handler
+ parent: root
+ }
+
+ ImageParticle {
+ id: img
+ groups: [emitter.color]
+ source: "images/blur-circle.png"
+ colorVariation: 0.1
+ color: emitter.color
+ alpha: 0
+ system: sys
+ }
+ }
+
+ ParticleSystem {
+ id: sys
+ ColoredEmitter {
+ color: "indianred"
+ }
+ ColoredEmitter {
+ color: "greenyellow"
+ }
+ ColoredEmitter {
+ color: "yellow"
+ }
+ ColoredEmitter {
+ color: "darkorange"
+ }
+ ColoredEmitter {
+ color: "violet"
+ }
+ }
+}
diff --git a/examples/quick/pointerhandlers/pointerhandlers.qml b/examples/quick/pointerhandlers/pointerhandlers.qml
index f063853793..049182fa8a 100644
--- a/examples/quick/pointerhandlers/pointerhandlers.qml
+++ b/examples/quick/pointerhandlers/pointerhandlers.qml
@@ -20,12 +20,14 @@ Rectangle {
addExample("multibuttons", "TapHandler: gesturePolicy (99 red balloons)", Qt.resolvedUrl("multibuttons.qml"))
addExample("pieMenu", "TapHandler: pie menu", Qt.resolvedUrl("pieMenu.qml"))
addExample("single point handler", "PointHandler: properties such as seat, device, modifiers, velocity, pressure", Qt.resolvedUrl("singlePointHandlerProperties.qml"))
+ addExample("multiflame", "PointHandler: particle flames around touchpoints", Qt.resolvedUrl("multiflame.qml"))
addExample("hover sidebar", "HoverHandler: a hierarchy of items sharing the hover state", Qt.resolvedUrl("sidebar.qml"))
addExample("joystick", "DragHandler: move one item inside another with any pointing device", Qt.resolvedUrl("joystick.qml"))
addExample("mixer", "DragHandler: drag multiple sliders with multiple fingers", Qt.resolvedUrl("mixer.qml"))
addExample("fling animation", "DragHandler: after dragging, use an animation to simulate momentum", Qt.resolvedUrl("flingAnimation.qml"))
addExample("pinch", "PinchHandler: scale, rotate and drag", Qt.resolvedUrl("pinchHandler.qml"))
addExample("map", "scale, pan, re-render at different resolutions", Qt.resolvedUrl("map.qml"))
+ addExample("corkboards", "editable, movable sticky notes in a ListView", Qt.resolvedUrl("corkboards.qml"))
addExample("fake Flickable", "implementation of a simplified Flickable using only Items, DragHandler and MomentumAnimation", Qt.resolvedUrl("fakeFlickable.qml"))
addExample("tablet canvas", "PointHandler and HoverHandler with a tablet: detect the stylus, and draw", Qt.resolvedUrl("tabletCanvasDrawing.qml"))
}
@@ -40,7 +42,7 @@ Rectangle {
model: 10
delegate: TouchpointFeedbackSprite { parent: glassPane }
}
-
- MouseFeedbackSprite { }
}
+
+ MouseFeedbackSprite { }
}
diff --git a/examples/quick/pointerhandlers/qml.qrc b/examples/quick/pointerhandlers/qml.qrc
index e9a39bc50c..237eb8eae0 100644
--- a/examples/quick/pointerhandlers/qml.qrc
+++ b/examples/quick/pointerhandlers/qml.qrc
@@ -1,11 +1,13 @@
<RCC>
- <qresource prefix="/pointerhandlers">
+ <qresource prefix="/qt/qml/pointerhandlers">
+ <file>corkboards.qml</file>
<file>flingAnimation.qml</file>
<file>fakeFlickable.qml</file>
<file>joystick.qml</file>
<file>map.qml</file>
<file>mixer.qml</file>
<file>multibuttons.qml</file>
+ <file>multiflame.qml</file>
<file>pieMenu.qml</file>
<file>pinchHandler.qml</file>
<file>pointerhandlers.qml</file>
@@ -15,6 +17,7 @@
<file>tapHandler.qml</file>
<file>components/Button.qml</file>
<file>components/CheckBox.qml</file>
+ <file>components/CorkPanel.qml</file>
<file>components/FakeFlickable.qml</file>
<file>components/FlashAnimation.qml</file>
<file>components/LeftDrawer.qml</file>
@@ -27,6 +30,10 @@
<file>images/arrowhead.png</file>
<file>images/balloon.png</file>
<file>components/images/checkmark.png</file>
+ <file>components/images/cork.jpg</file>
+ <file>components/images/note-yellow.png</file>
+ <file>components/images/tack.png</file>
+ <file>images/blur-circle.png</file>
<file>images/cursor-airbrush.png</file>
<file>images/cursor-eraser.png</file>
<file>images/cursor-felt-marker.png</file>
diff --git a/examples/quick/pointerhandlers/tapHandler.qml b/examples/quick/pointerhandlers/tapHandler.qml
index 178c067ce0..5891491695 100644
--- a/examples/quick/pointerhandlers/tapHandler.qml
+++ b/examples/quick/pointerhandlers/tapHandler.qml
@@ -6,20 +6,22 @@ import QtQuick.Layouts
import "components"
Item {
- width: 800
+ width: 1024
height: 480
Rectangle {
id: rect
anchors.fill: parent; anchors.margins: 40; anchors.topMargin: 60
- border.width: 3; border.color: "transparent"
- color: handler.pressed ? "lightsteelblue" : "darkgrey"
+ border.width: 4; border.color: "transparent"
+ color: handler.pressed ? "lightsteelblue" : "aliceblue"
TapHandler {
id: handler
acceptedButtons: (leftAllowedCB.checked ? Qt.LeftButton : Qt.NoButton) |
(middleAllowedCB.checked ? Qt.MiddleButton : Qt.NoButton) |
(rightAllowedCB.checked ? Qt.RightButton : Qt.NoButton)
+ exclusiveSignals: (singleExclusiveCB.checked ? TapHandler.SingleTap : TapHandler.NotExclusive) |
+ (doubleExclusiveCB.checked ? TapHandler.DoubleTap : TapHandler.NotExclusive)
gesturePolicy: (policyDragThresholdCB.checked ? TapHandler.DragThreshold :
policyWithinBoundsCB.checked ? TapHandler.WithinBounds :
policyDragWithinBoundsCB.checked ? TapHandler.DragWithinBounds :
@@ -30,6 +32,16 @@ Item {
borderBlink.blinkColor = "red"
borderBlink.start()
}
+ onSingleTapped: function(point, button) {
+ console.log("single-tapped button " + button + " @ " + point.scenePosition)
+ rect.border.width = 4
+ borderBlink.tapFeedback(button)
+ }
+ onDoubleTapped: function(point, button) {
+ console.log("double-tapped button " + button + " @ " + point.scenePosition)
+ rect.border.width = 12
+ borderBlink.tapFeedback(button)
+ }
onTapped: function(point, button) {
console.log("tapped button " + button + " @ " + point.scenePosition +
" on device '" + point.device.name + "' with modifiers " + handler.point.modifiers +
@@ -37,8 +49,6 @@ Item {
if (tapCount > 1) {
tapCountLabel.text = tapCount
flashAnimation.start()
- } else {
- borderBlink.tapFeedback(button)
}
}
onLongPressed: longPressFeedback.createObject(rect,
@@ -97,10 +107,10 @@ Item {
id: borderBlink
property color blinkColor: "red"
function tapFeedback(button) {
+ stop();
blinkColor = buttonToBlinkColor(button);
start();
}
- loops: 3
ScriptAction { script: rect.border.color = borderBlink.blinkColor }
PauseAnimation { duration: 100 }
ScriptAction { script: rect.border.color = "transparent" }
@@ -145,6 +155,18 @@ Item {
}
Text {
+ text: "exclusive signals:"
+ }
+ CheckBox {
+ id: singleExclusiveCB
+ text: "single"
+ }
+ CheckBox {
+ id: doubleExclusiveCB
+ text: "double"
+ }
+
+ Text {
text: "gesture policy:"
horizontalAlignment: Text.AlignRight
Layout.row: 1