diff options
Diffstat (limited to 'examples/quick/pointerhandlers')
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 Binary files differnew file mode 100644 index 0000000000..160bc002bf --- /dev/null +++ b/examples/quick/pointerhandlers/components/images/cork.jpg diff --git a/examples/quick/pointerhandlers/components/images/note-yellow.png b/examples/quick/pointerhandlers/components/images/note-yellow.png Binary files differnew file mode 100644 index 0000000000..3195952ad2 --- /dev/null +++ b/examples/quick/pointerhandlers/components/images/note-yellow.png diff --git a/examples/quick/pointerhandlers/components/images/tack.png b/examples/quick/pointerhandlers/components/images/tack.png Binary files differnew file mode 100644 index 0000000000..cef2d1cd23 --- /dev/null +++ b/examples/quick/pointerhandlers/components/images/tack.png 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 Binary files differnew file mode 100644 index 0000000000..5149665a07 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fakeflickable.jpg diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp Binary files differnew file mode 100644 index 0000000000..4b8794971e --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-fling.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg Binary files differnew file mode 100644 index 0000000000..c9d167b1e7 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-joystick.jpg diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp Binary files differnew file mode 100644 index 0000000000..b96b0cf90a --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-map.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp Binary files differnew file mode 100644 index 0000000000..f263458d12 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-mixer.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp Binary files differnew file mode 100644 index 0000000000..1d13805c64 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-multibutton.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp Binary files differnew file mode 100644 index 0000000000..cc5ca5d394 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-piemenu.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp Binary files differnew file mode 100644 index 0000000000..89f61251ab --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pinchhandler.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp Binary files differnew file mode 100644 index 0000000000..1a0ac33d0c --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-pointhandler.webp diff --git a/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp Binary files differnew file mode 100644 index 0000000000..162e97ea15 --- /dev/null +++ b/examples/quick/pointerhandlers/doc/images/pointerhandlers-example-taphandler.webp 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 Binary files differnew file mode 100644 index 0000000000..1b03cd0b2c --- /dev/null +++ b/examples/quick/pointerhandlers/images/blur-circle.png 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 |