Имитация щелчка мышью на QSlider не работает - PullRequest
0 голосов
/ 07 мая 2019

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

QCoreApplication::sendEvent();

, и он отлично работает для QPushButton и некоторых других компонентов.

Для QSlider (Горизонтальный ползунок в конструкторе)Я попробовал приведенный ниже код, который не работает.

QMouseEvent mousePressEvent(QEvent::MouseButtonPress,QPoint(50, 5), Qt::LeftButton, 0, 0);
QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mousePressEvent);

QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, QPoint(50, 5), Qt::LeftButton, 0, 0);
QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mouseReleaseEvent);

, но с QTest он работает нормально.

QTest::mouseClick(ui->horizontalSlider, Qt::LeftButton, Qt::NoModifier, QPoint(50, 5));

Любое предложение по исправлению того же было бы большой помощью.Заранее спасибо.

1 Ответ

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

Краткий ответ будет следующим:

// The following code should be changed
QMouseEvent mousePressEvent(QEvent::MouseButtonPress,QPoint(50, 5), Qt::LeftButton, 0, 0);
QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mousePressEvent);

QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, QPoint(50, 5), Qt::LeftButton, 0, 0);
QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mouseReleaseEvent);

// To the following one. Also, note that (QObject*) is not necessary, since QSlider is in the hierarchy with QObject, i.e. QObject is ancestor for the QSlider.
QMouseEvent mousePressEvent(QEvent::MouseButtonPress,QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::sendEvent(ui->horizontalSlider, &mousePressEvent);

QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::sendEvent(ui->horizontalSlider, &mouseReleaseEvent);

Это был бы короткий ответ. Более длинная его версия может использоваться любым, кто хотел бы, чтобы можно было определить, какие события необходимо использовать для имитации какого-либо поведения на элементах Qt.

Прежде всего, нам нужно выяснить, какой тип события фактически вводится в QSlider при нажатии на него кнопки мыши. Тогда мы сможем смоделировать это на самом деле. Для этого мы можем использовать фильтр событий. Для простоты давайте сначала воспользуемся этим:

class QSliderAnalyser
        : public QObject
{
    public:
        QSliderAnalyser()
        {
        }

        virtual ~QSliderAnalyser()
        {
        }

    protected:
        bool eventFilter(QObject* object, QEvent* event) override
        {
            qDebug() << event->type();

            return QObject::eventFilter(object, event);
        }
};

Затем мы устанавливаем этот фильтр на ваш QSlider экземпляр:

// Just keep in mind that memory is not managed in correct way here, and you should ensure proper cleanup of your elements on destruction.
ui->horizontalSlider->installEventFilter(new QSliderAnalyser());

После запуска приложения мы можем увидеть множество различных событий. Пример ниже (после пары взаимодействий с QSlider instance):

QEvent::Type(HoverMove)
QEvent::Type(HoverMove)
QEvent::Type(HoverMove)
QEvent::Type(HoverMove)
QEvent::Type(MouseButtonPress)
QEvent::Type(Paint)
QEvent::Type(MouseButtonRelease)
QEvent::Type(Paint)
QEvent::Type(HoverMove)

Наиболее интересная часть здесь следующая: QEvent :: Type (MouseButtonPress) и QEvent :: Type (MouseButtonRelease). Другими словами, QMouseEvent из другого типа моделируется. До этого момента вы, вероятно, сами понимали, что отправлять, то есть вы уже пытались отправить правильные события. Однако, может быть, параметры неверны? Это может быть так. Итак, давайте посмотрим на QMouseEvent аргументы конструктора класса:

QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)

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

        // Change "qDebug() << event->type();" to the following code.
        if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)
        {
            auto mouseEvent = static_cast<QMouseEvent*>(event);
            qDebug() << mouseEvent->type();
            qDebug() << mouseEvent->localPos();
            qDebug() << mouseEvent->windowPos();
            qDebug() << mouseEvent->screenPos();
            qDebug() << mouseEvent->button();
            qDebug() << mouseEvent->buttons();
            qDebug() << mouseEvent->modifiers();
            qDebug() << mouseEvent->source();
        }

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

QEvent::Type(MouseButtonPress)
QPointF(37,8)
QPointF(67,160)
QPointF(2747,550)
1
QFlags<Qt::MouseButtons>(LeftButton)
QFlags<Qt::KeyboardModifiers>(NoModifier)
Qt::MouseEventSource(MouseEventNotSynthesized)

QEvent::Type(MouseButtonRelease)
QPointF(37,8)
QPointF(67,160)
QPointF(2747,550)
1
QFlags<Qt::MouseButtons>(NoButton)
QFlags<Qt::KeyboardModifiers>(NoModifier)
Qt::MouseEventSource(MouseEventNotSynthesized)

Итак, что здесь можно сделать? Я думаю, что мы можем просто попытаться смоделировать событие как можно точнее и просто удалить значения одно за другим, чтобы увидеть минимально требуемое событие, которое будет обработано, как поведение, которое нужно наблюдать из Qt. Итак, изначально можно использовать следующий код:

QMouseEvent mousePressEvent(QEvent::MouseButtonPress, QPoint(37, 8), QPoint(67, 160), QPoint(2747, 550), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
QMouseEvent mouseReleaseEvent(QEvent::MouseButtonPress, QPoint(37, 8), QPoint(67, 160), QPoint(2747, 550), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);

QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mousePressEvent);
QCoreApplication::sendEvent((QObject*)ui->horizontalSlider, &mouseReleaseEvent);

И после некоторых наблюдений мы можем вывести следующее:

  1. Положение экрана не требуется.
  2. Положение окна тоже не нужно.
  3. Источник событий мыши тоже не нужен.
  4. Вы не обязаны использовать нажатие кнопки мыши И отпускать события. Вы можете просто нажать или отпустить мышь. Qt обработает даже этот тип поведения.
  5. В основном необходимо следующее: тип события мыши (т.е. нажатие и отпускание), локальное положение, кнопка, которая была нажата и отпущена, и модификаторы клавиатуры.

Таким образом, код может быть переписан следующими способами и будет работать:

// Option One
QMouseEvent mousePressEvent(QEvent::MouseButtonPress, QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QMouseEvent mouseReleaseEvent(QEvent::MouseButtonPress, QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

QCoreApplication::sendEvent(ui->horizontalSlider, &mousePressEvent);
QCoreApplication::sendEvent(ui->horizontalSlider, &mouseReleaseEvent);

// Option Two
QMouseEvent mousePressEvent(QEvent::MouseButtonPress, QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

QCoreApplication::sendEvent(ui->horizontalSlider, &mousePressEvent);

// Option Three
QMouseEvent mousePressEvent(QEvent::MouseButtonPress, QPoint(50, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

QCoreApplication::sendEvent(ui->horizontalSlider, &mousePressEvent);

Таким образом, я показал возможности того, как определить, какой тип событий приводит к поведению, которое Qt обрабатывает в виджетах. Надеюсь, мой ответ был ясным и достаточно полезным.

...