Как симулировать щелчок мышью с помощью сенсорных данных? - PullRequest
2 голосов
/ 29 мая 2019

Я работаю над приложением Qt5, чтобы попытаться использовать необработанные входные данные с сенсорного экрана, потому что касание не полностью поддерживается моим ядром Linux (2.6.32). Я написал парсер для необработанных данных, поступающих из / dev / input / eventX , потому что, хотя X не поддерживает touch, события все еще там.

Я в состоянии прочитать события очень хорошо, и написал оболочку «TouchPoint», которая содержит ID и (x, y) координаты каждой точки касания, а также логическое значение, указывающее, есть ли точка касания в данный момент «активен» (то есть: у пользователя в данный момент есть этот палец на экране). Стоит отметить, что я также выводю количество точек касания, находящихся в данный момент на экране, и значение является точным.

Моя проблема в том, что я не могу понять, как точно имитировать щелчок мышью. В случае событий multi-touch в Linux каждой точке касания назначается «идентификатор отслеживания», когда пользователь нажимает пальцем на экран, и когда эта точка поднимается, генерируется событие, устанавливающее идентификатор отслеживания слота в -1. Я использую это изменение идентификатора с некоторого значения на -1, чтобы указать, что точка касания "вниз" или нет:

void TouchPoint::setID(int nid) {
    if((id == -1) && (nid >= 0)) down = true;
    else if(nid == -1) down = false;
    id = nid;
}

Итак, чтобы попытаться смоделировать щелчок мыши, я делаю это, когда читается событие отслеживания ID:

else if(event.code == ABS_MT_TRACKING_ID) {
    bool before = touchPoints[cSlot].isDown(); // where cSlot is the current slot the events are referring to
    touchPoints[cSlot].setID(event.value);
    bool after = touchPoints[cSlot].isDown();

    if(!before && after) touch(touchPoints[cSlot]);
}

А затем сенсорный метод делает это:

void MainWindow::touch(TouchPoint tp) {
    if(ui->touchMe->rect().contains(QPoint(tp.getX(), tp.getY()))) {
        on_touchMe_clicked();
    }
}

Кнопка не реагирует на мое непосредственное прикосновение к ней, но иногда, если я дико провожу пальцами по экрану, отображается окно сообщения, которое должно отображаться при нажатии, но когда это происходит, мои пальцы всегда находятся где-то на другом площадь экрана.

Кто-нибудь может подумать о чем-то, что я могу здесь делать неправильно? Мой метод проверки, чтобы видеть, находится ли точка касания в пределах кнопки, неправильна? Или моя логика заключается в том, что я неправильно отслеживаю состояние отключения точек касания? Или что-то еще целиком?

ОБНОВЛЕНИЕ: Я только что заметил две вещи, выводя координаты экрана как местоположения касания, так и местоположения кнопки.

  1. Разрешение дигитайзера больше, чем разрешение экрана, поэтому мне нужно было масштабировать координаты X и Y из исходных событий.
  2. Мои координаты смещены, потому что они являются экранными координатами.

ОБНОВЛЕНИЕ 2: Теперь я рассмотрел две проблемы, упомянутые в моем последнем обновлении, но я все еще не могу понять, как точно смоделировать событие касания / мыши, чтобы иметь возможность взаимодействовать с интерфейсом. Я также изменил свой класс TouchPoint, чтобы иметь логический флаг, указывающий, была ли обновлена ​​точка касания, которая имеет значение true, когда обновляется идентификатор отслеживания, и сбрасывается при возникновении события EV_SYN. Это так, чтобы я мог получить события положения X и Y перед созданием события для приложения. Я попробовал следующее:

  1. Использование класса QApplication для публикации события мыши в виджете QApplication :: desktop () -> screen (), который имеет позицию точки касания.
  2. Использование класса QTest для вызова touchEvent в виджет QApplication :: desktop () -> screen () с использованием методов press и release для заданного слота и положения точки касания, а затем с помощью события bool (QEvent *) ) метод, чтобы попытаться поймать событие. Я также включил атрибут WA_AcceptTouchEvents в главном окне.

Ни одно из этих действий, по какой-то причине, когда у меня есть метод "событие bool (QEvent *)" , сигнал, излучаемый потоком, читает / dev / input / eventX не вызывает слот в классе главного окна. и я не могу найти какой-либо другой метод для моделирования событий. У кого-нибудь есть идеи?

1 Ответ

1 голос
/ 31 мая 2019

Вы писали, что иногда вы получаете сообщение «щелкнуло» по окну вашего сообщения, когда ваши пальцы находятся в «неправильном положении», поэтому звучит так, будто вы смешиваете глобальные координаты экрана и локальные координаты виджета.Кажется, в вашем MainWindow::touch вы пытаетесь проверить, находится ли точка в глобальных экранных координатах, например (530, 815), внутри геометрии виджета (в его локальных координатах). QWidget :: rect () возвращает внутреннюю геометрию кнопки (виджета), то есть прямоугольник ширины и высоты виджета, например (0, 0, 60, 100).

У вас естьпереместить прямоугольник в правильное положение в глобальных экранных координатах. QWidget :: pos () возвращает локальную позицию виджета его родителю.Вы можете использовать QWidget :: mapToGlobal для перевода координатной позиции виджета в глобальные координаты экрана.Тогда ваш прямоугольник будет что-то вроде (500, 850, 60, 100), и вы должны получить удар и получить слот с именем.

Однако лучше использовать QApplication :: widgetAt чтобы получить виджет в определенной позиции на экране и сгенерировать для него щелчок мыши.

Вы можете сгенерировать щелчок мыши для виджета, опубликовав нажатие и отпустив его, как показано ниже:

QPoint screenPos = QPoint(tp.getX(), tp.getY());
QWidget *targetWidget = QApplication::widgetAt(screenPos);

QPoint localPos = targetWidget->mapFromGlobal(screenPos); 
QMouseEvent *eventPress = new QMouseEvent(QEvent::MouseButtonPress, localPos, screenPos, Qt::LeftButton, Qt::LeftButton,  Qt::NoModifier);
QApplication::postEvent(targetWidget, eventPress);
QMouseEvent *eventRelease = new QMouseEvent(QEvent::MouseButtonRelease, localPos, screenPos, Qt::LeftButton, Qt::LeftButton,  Qt::NoModifier);
QApplication::postEvent(targetWidget, eventRelease);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...