Как принять события касания в Qt6?

Я пытался принимать события касания в Qt6 следующим образом: в main.cpp:

QApplication::setAttribute(Qt::ApplicationAttribute::WA_AcceptTouchEvents);

error: no member named 'WA_AcceptTouchEvents' in 'Qt::ApplicationAttribute'

IntelliSense показывает, что Qt::ApplicationAttribute имеет WA_AcceptTouchEvents. Но я думаю, что это ошибка Qt Creator, потому что в WA_AcceptTouchEvents нет Qt::ApplicationAttribute:

и я попытался запустить этот код:

QApplication::setAttribute(Qt::WA_AcceptTouchEvents);

error: cannot initialize a parameter of type 'Qt::ApplicationAttribute' with an rvalue of type 'Qt::WidgetAttribute'

Я пытался принять это в конструкторе окна, но у QOpenGLWindow нет метода setAttribute:

error: use of undeclared identifier 'setAttribute'; did you mean 'QInputMethodEvent::Attribute'?

OpenGLWindow::OpenGLWindow()
{
    setTitle("OpenGL ES 2.0, Qt6, C++");
    resize(350, 350);
    setAttribute(Qt::WA_AcceptTouchEvents);
}

Мой профайл:

QT += core gui opengl widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# disables all the APIs deprecated before Qt 6.0.0
# DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000

SOURCES += \
    main.cpp \
    opengl_window.cpp

HEADERS += \
    opengl_window.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

Добавлен

musicamante разместил следующую ссылку и цитату в комментариях ниже:

документация (Обработка событий), «В отличие от виджетов, QWindows всегда получают события касания, нет необходимости соглашаться. При работе напрямую с QWindow достаточно переопределить QWindow::touchEvent()»

Но когда я запускаю следующий код на реальном устройстве, прикасаюсь к экрану (он печатает counter = 0), удерживая палец на экране, пытаюсь коснуться другим пальцем и не печатаю следующую строку, как counter = 1. Такое впечатление, что мультитач отключен.

void OpenGLWindow::touchEvent(QTouchEvent *event)
{
    switch (event->type())
    {
        case QEvent::TouchBegin:
            qDebug() << "counter = " << m_counter;
            m_counter++;
            break;
    }
}

Перекрестная ссылка: https://forum.qt.io/topic/155009/how-to-accept-touch-events-in-qt6

Пожалуйста, указывайте код как код, а не изображения.

pptaszni 01.03.2024 14:25

Компилятор прав - в Qt::ApplicationAttribute нет WA_AcceptTouchEvents, только ion Qt::WidgetAttribute

chehrlic 01.03.2024 15:07
Документы QT говорят, что вам нужно QWidget::setAttribute(), так что же такое OpenGLWindow?
pptaszni 01.03.2024 15:58

Кажется, вы пробуете что-то случайно. Как должно быть ясно из документации, перечисления WA_* являются частью атрибутов виджета, которые по очевидным причинам не могут быть произвольно использованы для чего-либо, кроме виджетов, таких как объекты QApplication или QWindow. Кроме того, опять же из документации (Обработка событий): «В отличие от виджетов, QWindows всегда получают события касания, нет необходимости соглашаться. При работе напрямую с QWindow достаточно переопределить QWindow::touchEvent() ".

musicamante 01.03.2024 16:39

@chehrlic IntelliSense показывает, что Qt::ApplicationAttribute имеет WA_AcceptTouchEvents. Я опубликовал скриншот. Я думаю, что это ошибка Qt Creator.

8Observer8 01.03.2024 22:27

@pptaszni Я удалил изображения. Я думал, так будет понятнее.

8Observer8 01.03.2024 22:29

@musicamante Но когда я запускаю код с помощью touchEvent (см. код в моем посте) на реальном устройстве, прикасаюсь к экрану (он печатает counter = 0), удерживая палец на экране, пытаюсь коснуться другим пальцем, но не получается напечатайте следующую строку, например counter = 1. Такое впечатление, что мультитач отключен.

8Observer8 01.03.2024 22:48

@8Observer8: поскольку в QtCreator нет IntelliSense, я не знаю, что вы пытаетесь мне сказать. Здесь нет необходимости в полной квалификации значения перечисления, поскольку это простое перечисление, а не класс перечисления.

chehrlic 01.03.2024 23:40

@8Observer8 QTouchEvent группирует несколько точек касания, добавление пальца создает не новое событие TouchBegin, а событие TouchUpdate, вам необходимо принять событие начала, чтобы получать события обновления, аналогично тому, что происходит с событиями MouseButtonPress и MouseMove. Все это объяснено в том же разделе, на который я дал ссылку выше, вы действительно все это прочитали?

musicamante 02.03.2024 00:02

@chehrlic Да, извини. Qt Creator не имеет IntelliSense, поскольку «IntelliSense — это технология автозаполнения Microsoft, наиболее известная в Microsoft Visual Studio. Добавляет имя функции при вводе начальных букв». Я не знаю, как называется технология автодополнения в Qt Creator. Я просто хотел отметить, что система завершения в Qt Creator предполагает, что WA_AcceptTouchEvents находится в Qt::ApplicationAttribute.

8Observer8 02.03.2024 01:48

@musicamante Спасибо большое! Добавил решение в конец темы.

8Observer8 02.03.2024 01:50

Просто на заметку на будущее. Если я использую QOpenGLWidget вместо QOpenGLWindow, мне придется вызвать конструктор: setAttribute(Qt::WidgetAttribute::WA_AcceptTouchEvents); Неправильно вызывать следующую команду внутри main.cpp: QApplication::setAttribute(Qt::WidgetAttribute::WA_AcceptTou‌​chEvents);

8Observer8 02.03.2024 02:12

Я написал решение своей проблемы здесь: forum.qt.io/topic/155009/…

8Observer8 02.03.2024 02:13

@8Observer8 Пожалуйста, не оставляйте ответы в теле вопроса, сайт так не работает. Я проголосовал за возобновление вашего вопроса, как только вы сможете опубликовать свое решение в качестве фактического ответа, используя соответствующую кнопку. Кроме того, избегайте добавления ссылок для перекрестных публикаций (вы уже делали это в прошлом): если другая ссылка не предоставляет дополнительную информацию, которая фактически расширяет/объясняет то, что вы здесь уже пишете, у кого-либо нет причин проходить полную поток, который, возможно, будет содержать ту же информацию, которую вы уже предоставили.

musicamante 02.03.2024 02:13

@8Observer8 Этот «неправильный вызов», очевидно, неверен по причинам, объясненным выше: вы можете устанавливать атрибуты виджетов в виджетах, а не в приложении. Нет необходимости это делать, так как это должно быть совершенно ясно из соответствующей документации QWidget.setAttribute() или QCoreApplication.setAttribute(). Как уже было сказано, вам нужно уделять больше внимания документации и быть более терпеливым в обучении/решении.

musicamante 02.03.2024 02:25

@musicamante, почему, если я позвоню print(dir(Qt.ApplicationAttribute)) в PyQt6, я не увижу WA_AcceptTouchEvents? Qt Creator не должен показывать WA_AcceptTouchEvents, если я печатаю Qt::ApplicationAttribute::

8Observer8 02.03.2024 02:40

@musicamante Я создаю тему: «Qt Creator предполагает, что WA_AcceptTouchEvents находится в Qt::ApplicationAttribute» forum.qt.io/topic/155020/…

8Observer8 02.03.2024 02:43

@8Observer8 Автодополнение — это просто интерпретируемое (и не всегда надежное) расширение семантики, а не правильный логический синтаксис: значение имеет фактическая реализация, выполняемая во время компиляции/выполнения. print(dir(Qt.ApplicationAttribute)), очевидно, будет отображать перечисления AA_* (ApplicationAttribute), а не WA_*: завершение основано на автоматическом анализе и следует независимой логике, которая может быть несовместима с интерпретатором/компилятором. Это может быть ошибка Creator, но это совершенно не имеет значения: Python (и C++) обращается к реальным объектам и ApplicationAttribute содержит только AA_* перечисления.

musicamante 02.03.2024 03:01
3
18
155
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как написал в комментариях musicamante, ответ есть в документации:

из документации (Обработка событий), «В отличие от виджетов, QWindows всегда получают события касания, нет необходимости соглашаться. При работе напрямую с QWindow достаточно переопределить QWindow::touchEvent()».

Очень полезная заметка о мультитачах от musicamante:

QTouchEvent группирует несколько точек касания, добавление пальца создает не новое TouchBegin, а событие TouchUpdate, вам необходимо принять событие начала, чтобы получать события обновления, аналогично тому, что происходит с событиями MouseButtonPress и MouseMove.

Мне следует уделять больше внимания документации.

Этот пример кода работает для меня:

opengl_window.h

#ifndef OPENGL_WINDOW_H
#define OPENGL_WINDOW_H

#include <QtGui/QTouchEvent>
#include <QtOpenGL/QOpenGLWindow>

class OpenGLWindow : public QOpenGLWindow
{
    Q_OBJECT

public:
    OpenGLWindow();

private:
    void touchEvent(QTouchEvent *event) override;
    int m_counter = 0;
};

#endif // OPENGL_WINDOW_H

opengl_window.cpp

#include "opengl_window.h"

OpenGLWindow::OpenGLWindow()
{
    setTitle("OpenGL ES 2.0, Qt6, C++");
    resize(350, 350);
}

void OpenGLWindow::touchEvent(QTouchEvent *event)
{
    switch (event->type())
    {
        case QEvent::TouchBegin:
            qDebug() << "touch begin";
            event->accept();
            break;
        case QEvent::TouchEnd:
            qDebug() << "touch end";
            break;
        case QEvent::TouchUpdate:
            qDebug() << "counter = " << m_counter;
            m_counter++;
            for (int i = 0; i < event->points().length(); i++) {
                int x = event->points()[i].position().x();
                int y = event->points()[i].position().y();
                qDebug() << x << " " << y;
            }
            break;
    }
}

main.cpp

#include <QtWidgets/QApplication>
#include "opengl_window.h"

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
    QApplication a(argc, argv);
    OpenGLWindow w;
    w.show();
    return a.exec();
}

про

QT += core gui opengl widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# disables all the APIs deprecated before Qt 6.0.0
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000

SOURCES += \
    main.cpp \
    opengl_window.cpp

HEADERS += \
    opengl_window.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

Другие вопросы по теме