模拟鼠标单击QSlider不起作用

时间:2019-05-07 13:46:13

标签: qt qwidget

我正在尝试使用

模拟小部件上的鼠标点击
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 个答案:

答案 0 :(得分:1)

简短的回答如下:

// 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实例进行了几次互动之后):

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在小部件上处理行为的可能性。希望我的答案很明确而且很有帮助。