Begrüßen Sie den Qt Quick-Pointer-Handler

Wir wissen, dass die Multi-Touch-Unterstützung von Qt Quick im Laufe der Jahre in vielen seiner Anwendungsfälle unzureichend war. Wir haben eine PinchArea , um mit zwei Fingern zu zoomen, zu drehen und zu ziehen; und MultiPointTouchArea , die verwendet werden können, um eine Art interaktives Feedback für die Berührungspunkte anzuzeigen, oder vielleicht könnten Sie eine Zustandsmaschine in JavaScript schreiben, um eine Art Geste zu erkennen. Was den Rest von Qt Quick betrifft, so sind die Hauptprobleme: 1) Unterstützung für Mausereignisse; 2) Qt geht davon aus, dass es nur eine Maus gibt (den "primären Mauszeiger"); 3) QMouseEvent und QTouchEvent (und einige mehr) haben keine geeignete Zwischenbasisklasse, daher werden sie unabhängig voneinander geliefert; 4), was anfangs schwierig war, Touch-Events als Maus-Events zu behandeln und auf die gleiche Weise zu liefern. Das Ergebnis ist also, dass Sie nicht gleichzeitig mit zwei MouseAreas oder Flickables interagieren können, z. Es bedeutet auch, dass Sie nicht zwei Tasten gleichzeitig drücken oder zwei Schieberegler gleichzeitig ziehen können, wenn sie mit MouseArea implementiert sind.


Zuerst hatte ich gehofft, dies zu beheben, indem ich MouseArea und Flickable zu separaten Touch-Ereignissen machte. Die Patches dafür waren ziemlich komplex und fügten eine Menge doppelter Logik für einen vollständig parallelen Bereitstellungspfad hinzu: QMouseEvent würde einen Pfad nehmen und QTouchEvent den anderen, in der Hoffnung, dass die Interaktion so gut wie möglich funktionieren würde. Es war monatelange Arbeit, und am Ende hat es meistens funktioniert ... aber es war schwierig, alle bestehenden Autotests zu bestehen, und die Kollegen befürchteten, dass dies eine Verhaltensänderung war. MouseArea, wie der Name schon sagt, verarbeitet Mausereignisse. Als es also anfing, Touch-Ereignisse separat zu behandeln, wurde sein Name missbraucht. Plötzlich konnten Sie in Apps und Steuerungssets, die nicht dafür entwickelt wurden, zwei Schaltflächen, Registerkarten oder Optionsfelder gleichzeitig drücken. (Also haben wir versucht, eine boolsche Eigenschaft hinzuzufügen, die gesetzt werden könnte, aber es auf jeder MouseArea setzen zu müssen, wäre hässlich.) MouseArea und Flickable müssen auch viel interagieren, also mussten Änderungen zusammen vorgenommen werden, damit es funktioniert. Dies war möglich, wurde aber in Qt 5.5 aufgrund von Ungenauigkeiten nicht hinzugefügt.

Also wählten wir am Ende einen anderen Weg, nachdem wir eine sinnvolle Kombination der vorgeschlagenen Ideen gefunden hatten.

Eine Idee war, dass wir, da wir die QEvent-Hierarchie aufgrund des Binärkompatibilitätsbefehls nicht (noch nicht) umgestalten können, stattdessen Wrapper-Klassen erstellen könnten, die Ereignisse so aussehen lassen, wie wir es wollen, komplett mit Eigenschaften zum Nutzen von QML. und stellen Sie diese Wrapper-Klassen anstelle der regulären bereit, indem Sie einen einzigen Ereignisübermittlungspfad für QQuickWindow und QQuickItem verwenden.

Eine andere Idee war, zu erkennen, dass das dynamische Erstellen und Zerstören dieser Wrapper-Ereignisse dumm ist: Stattdessen begannen wir, einen Pool von Instanzen zu verwenden, wie wir es in anderen Fällen taten, wenn das "Ereignis" -Objekt von einem Signal ausgegeben wird (z. B. das Objekt object ausgegeben von MouseArea .positionChanged ist seit Qt 5.8 immer dieselbe Instanz). Mit dieser Optimierung ist das Verschieben eines Ereignisses zu einem anderen kein großer Leistungseinbruch mehr.

Eine weitere Idee wurde aufgeworfen: Vielleicht wäre es schön, wenn die Behandlung des Zeigegerät-Ereignisses so einfach wäre wie die Verwendung der Tasten, an die die Eigenschaft gebunden ist: zum Beispiel Mouse.onClicked: {...} oder PointingDevice. onTapped: {...} Aber bald darauf kam die Erkenntnis, dass es nur eine Instanz einer angehängten Eigenschaft pro Element geben kann, an das sie angehängt ist. Eines der Probleme mit MouseArea besteht darin, dass es versucht, zu viel zu tun, sodass es keinen Sinn macht, einfach die gesamte Funktionalität in einem monolithischen MouseAttached neu zu implementieren. Wir wollten in der Lage sein, einen Klick oder Tap zu verarbeiten, ohne uns darum zu kümmern, von welchem Gerät es kommt, denn das muss jedes Button-Steuerelement tun. Dasselbe gilt für jede Geste, die mit einer Maus oder einem Finger ausgeführt werden kann. Vielleicht sollte es eine angefügte Eigenschaft pro Geste geben und nicht eine pro Gerätetyp?

Da QML eine deklarative Sprache ist, ist es schön, Einschränkungen deklarieren zu können, anstatt if/else-Anweisungen in JavaScript-Callbacks zu schreiben. Wenn das Objekt, das die Ereignisse verarbeitet, so konzipiert ist, dass es sich nicht darum kümmert, von welchem Gerät die Geste stammt, wird es immer noch Fälle geben, in denen sich Ihre Anwendung darum kümmert: Sie möchten verschiedene Aktionen ausführen, je nachdem, ob es auf gedrückt wird Touchscreen oder mit der rechten Maustaste, oder Sie möchten etwas anderes tun, wenn die Steuerungstaste beim Ziehen eines Objekts gedrückt gehalten wird. Indem wir mehrere Instanzen dieser Handler-Objekte bereitstellen, können wir Einschränkungen für sie deklarieren, indem wir Eigenschaften festlegen. Es sollte gut sein, so viele Fälle zu haben, wie Sie brauchen. Jede Instanz sollte leichtgewichtig sein, damit Sie nicht befürchten müssen, zu viele Instanzen zu haben. Die Implementierung sollte in C++ erfolgen und einfach und übersichtlich sein. Jeder Hundeführer sollte eine Sache oder höchstens ein paar sehr nahe liegende Dinge tun und sie gut machen.

Vorerst haben uns diese Probleme von der Idee abgelenkt, angehängte Eigenschaften zu verwenden. Stattdessen haben wir eine neue Klasse von Klassen in Qt Quick: Pointer-Handler.

Ein Zeigerhandler ist ein Objekttyp, den Sie in jedem Element deklarieren können, das Ereignisse von Zeigegeräten im Auftrag dieses Elements verarbeitet. Sie können so viele davon deklarieren, wie Sie möchten, normalerweise einen für jedes Interaktionsszenario. Все общие ограничения, о которых мы могли думать, являются декларируемыми: вы можете заставить обработчика реагировать только в том случае, если это событие касания, только для определенных кнопок мыши, только если правильное количество пальцев нажато в пределах элемента, только если специальная клавиша-модификатор usw.

Ziehbare Bälle

Reguläre Gesten werden durch ihre eigenen Handler-Typen dargestellt. Zum Beispiel, wenn Sie erklären

Rectangle {
    width: 50; height: 50; color: "green"
    DragHandler { }
}

dann haben Sie ein Rechteck, das mit der Maus oder Berührung über die Bühne gezogen werden kann (http://doc-snapshots.qt.io/qt5-5.10/qml-qt-labs-handlers-draghandler.html), ohne zu schreiben Javascript und sogar ohne den Handler an seine Eltern binden zu müssen. Es hat eine Ziel -Eigenschaft und der Standardwert ist sein übergeordnetes Element. (Aber indem Sie das Ziel auf ein anderes Element setzen, können Sie Ereignisse innerhalb eines Elements erfassen, aber das andere manipulieren.)

Wenn Sie diese beiden grünen Rechtecke mit DragHandlern darin haben, können Sie sie natürlich beide gleichzeitig mit verschiedenen Fingern ziehen.

Jeder Pointer-Handler ist ein QObject, aber kein QQuickItem und hat nicht zu viele eigene Variablen, sodass jede Instanz etwa so klein ist wie eine QObject-Unterklasse.

Jeder Einzelpunkt-Handler hat eine point -Eigenschaft, um alle Details bereitzustellen, die wir über den Berührungspunkt oder Mausklick finden können. Es gibt die Eigenschaften pressure und ellipseDiameters : Einige Geräte verfügen möglicherweise über Kraftsensoren, während andere die Kontaktpfadgröße messen (aber viele Geräte bieten dies nicht). Solche Geräte haben eine Geschwindigkeit -Eigenschaft, die garantiert bestimmt werden kann: Wir berechnen und mitteln die Geschwindigkeit über die letzten paar Bewegungen für eine etwas sanftere Reaktion. Die verfügbare Geschwindigkeit kann möglicherweise geschwindigkeitsabhängige Gesten aktivieren: Vielleicht muss der Klick mit einer bestimmten Mindestgeschwindigkeit ausgeführt werden. (Ist dies der richtige Weg, um einen Klick von einem Ziehen zu unterscheiden? Es war vorher nicht einfach, diese Unterscheidung zu treffen.) Oder, wenn Sie beim Loslassen Geschwindigkeit haben, kann die Ziehgeste mit Schwung enden: Das Objekt bewegt sich kurz Abstand in eine Richtung. Es macht Ihre Schnittstelle lebendiger. Bisher haben wir MomentumAnimation nicht in einen unterstützten Animationstyp formalisiert, aber es gibt einen reinen QML-Prototypen in tests/manual/pointer/content/MomentumAnimation.qml.

Pocken

TapHandler verarbeitet alle Gesten zum Tippen und Loslassen: einzelnes schnelles Tippen oder Klicken, doppeltes Tippen, andere Zahlen antippen, ein Antippen für eine konfigurierbare Zeitdauer oder verschiedene Zeitdauern auf ganz einzigartige Weise halten (Wenn Sie den Touchscreen berühren, ist oft kein Ton zu hören, aber Sie können die Maustaste drücken, Daher dachten wir, dass "Tippen" eine zuverlässigere Zukunft für diese Geste ist als "Klicken".) Sie können Feedback proportional zur Dauer des Klicks anzeigen (ein sich erweiternder Kreis, ein Fortschrittsbalken oder ähnliches).

Kneife mich, wenn es wahr ist

Es gibt PinchHandler . Wenn Sie es in einem Element deklarieren, können Sie dieses Objekt mit Pinch-Gesten skalieren, drehen und ziehen. Sie können jeden beliebigen Teil des Elements skalieren (verbessert in PinchArea). Es kann auch mehr Finger verarbeiten: Sie können PinchHandler {minimumTouchPoints: 3} deklarieren, um eine Pinch-Geste mit drei Fingern zu erfordern. Alle Transformationen beziehen sich dann auf den Mittelpunkt zwischen den drei Fingern, und die Skalierung bezieht sich auf die durchschnittliche Zunahme oder Abnahme der Spreizung zwischen ihnen. Die Idee kam von der Tatsache, dass einige Ubuntu-Versionen eine Drei-Finger-Prise verwenden, um Fenster zu manipulieren: Offenbar dachten sie, dass der Inhalt in einem Fenster für Zwei-Finger-Gesten verwendet werden könnte, aber die meisten Anwendungen verwenden also keine drei Finger Es ist in Ordnung, die Drei-Finger-Prise zum Zoomen und Verschieben von Fenstern auf dem Desktop zu reservieren. Da Sie nun einen Wayland-Composer in QML schreiben können, können Sie diese Erfahrung leicht reproduzieren.

Zu den Punkten gelangen

Schließlich gibt es noch PointHandler . Im Gegensatz zu den anderen manipuliert es sein Zielelement nicht: Es existiert nur, um eine Punkteigenschaft bereitzustellen. Es ähnelt einem eigenständigen TouchPoint in einer MultiPointTouchArea und kann für denselben Zweck verwendet werden: um interaktives Feedback als Berührungspunkte oder als Mauszeiger bereitzustellen, der sich in der Szene bewegt. Im Gegensatz zu MultiPointTouchArea erfasst es Berührungspunkte oder die Maus nicht ausschließlich, sodass dieses interaktive Feedback nicht die gleichzeitige Interaktion mit anderen Handlern auf anderen Elementen verhindert. Die Animation auf dieser Seite verwendet es, um die Finger-Sprites dazu zu bringen, meinen Fingern zu folgen.

Ist das alles?

Also komme ich jetzt zu den Gründen, warum dieses Zeug in der Tech Preview bei 5.10 ist. Ein Grund dafür ist, dass es unvollständig ist: Uns fehlt noch die Unterstützung für Mouseover, Mausrad und Tablettstifte (im Moment wird der Stift noch als Maus behandelt). Keiner der Handler ist geschwindigkeitsempfindlich. Wir können uns ein paar weitere Handler vorstellen, die geschrieben werden könnten. Es sollte eine offene C++-API geben, damit Sie Ihre eigene erstellen können. Handler und Flickable kommen ein bisschen miteinander aus, aber Flickable ist ein komplexes monolithisches Objekt und wir denken, dass es später umgestaltet werden könnte. Es gibt einen manuellen FakeFlickable -Test, der zeigt, wie Sie die meisten Ihrer Funktionen in QML mit zwei regulären Elementen, plus einem DragHandler und einigen Animationen nachbilden können.

Ein weiterer Grund ist die Namensgebung. „Zeiger-Handler“ klingt für sich genommen ganz okay, aber es gibt eine bereits vorhandene Terminologie, die es verwirrend macht: Ein Zeiger kann eine Variable sein, die auf einen Speicherort zeigt (aber das meinen wir hier nicht), und ein Handler kann eine umgekehrte Funktion sein Sortieraufruf, den Sie in JavaScript schreiben. Wenn Sie TapHandler {onActiveChanged: ...} schreiben, sagen Sie dann, dass Ihr Handler einen Handler hat? Wir könnten stattdessen das Wort "Rückruf" verwenden, aber das ist in manchen Kreisen ein Anachronismus, und in QML sind unsere Gewohnheiten jetzt schwer zu ändern.

Ein weiterer Grund ist, dass QtLocation einige komplexe Anwendungsfälle hat, die wir als Beispiel verwenden möchten, um zu beweisen, dass es möglich ist, die Karte (und alle interaktiven Inhalte darauf) mit etwas lesbarem Code zu verschieben.

Vielleicht folge ich dem später mit einem weiteren Beitrag über eine andere Art der Gestenerkennung und wie sich das darauf auswirken könnte, wie wir in Zukunft über Pointer-Handler denken. Ich habe das Konzept der passiven Erfassung noch nicht erklärt. Es gibt auch weitere Informationen zum Erstellen von Komponenten, die intern Zeigerhandler verwenden, aber der Urheberrechtsautor kann das Verhalten bei Bedarf überschreiben.

Momentan befinden sich Pointer-Handler also in der Tech Preview in 5.10. Wir hoffen, dass Sie lange Freude daran haben, damit zu spielen. Vor allem, wenn Sie einige alte Frustrationen über Interaktionsszenarien haben, die vorher nicht möglich waren. Wenn Sie außerdem jemals eine Touch-Benutzeroberfläche (vielleicht sogar für mehrere Benutzer?) erstellen wollten, ohne C++-Event-Forwarding- und QObject-Event-Filtering-Dreck zu schreiben. Wir müssen anfangen, Feedback von allen mit einzigartigen Anwendungsfällen zu erhalten, während wir die Freiheit haben, bei Bedarf große Änderungen vorzunehmen, um die Dinge für Sie einfacher zu machen.

Bisher waren die Use Cases meist in tests/manual/pointer . Die Testquelle ist nicht im Release-Build-Paket enthalten, um sie also auszuprobieren, müssen Sie die Qt-Quellpakete herunterladen oder aus dem [git]-Repository (http://code.qt.io/cgit/qt/qtdeclarative .git/tree /tests/manual/pointer/) . Einige von ihnen können in Beispiele für kommende Versionen umgewandelt werden.

Da sich dies in der technischen Vorschau befindet, wird die Implementierung während der 5.10-Serie weiter verbessert, folgen Sie also dem 5.10-Git-Zweig , um über die neuesten Funktionen und Fehlerbehebungen auf dem Laufenden zu bleiben.

Artikel geschrieben von: Shawn Rutledge | Donnerstag, 23.11.2017

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken