鼠标移动事件未被调用

6

我需要获取小部件内的鼠标移动:

使用事件过滤器不可行,因为它将安装在QApplication上。该小部件在类型层次结构中很低。将此小部件传递到创建QApplication对象的主函数中会破坏代码。

因此,我实现了

void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent *event);

在小部件中。
没有任何事件被调用。 即使在中央小部件和实际需要事件的小部件上都将鼠标跟踪设置为true,函数也不会被调用:
centralWidget->setMouseTracking(true);

如何在Qt中为QWidget的自定义子类获取鼠标事件?
更新:这是.h文件:
class Plot : public QWidget
{
    Q_OBJECT
//...

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent * event);
    void mouseMoveEvent(QMouseEvent *event);

更新:

我尝试了eventFilter方法。

在.h文件中:

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent * event);
    void mouseMoveEvent(QMouseEvent *event);

    bool eventFilter(QObject* object, QEvent* event);

在 .cpp 文件中:

void Plot::mousePressEvent(QMouseEvent *event){
//...
}
void Plot::mouseMoveEvent(QMouseEvent *event){

}
void Plot::mouseReleaseEvent(QMouseEvent *event){

}

bool Plot::eventFilter(QObject* object, QEvent* event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent* mev=static_cast<QMouseEvent*>(event);

        qDebug()<<mev->x();
    }
   return false;
}

然后在我的 qWidget 构造函数中:

this->installEventFilter(this);

代码编译和运行正常。 在事件过滤器中if语句处设置断点可以停止程序,调用eventFilter方法。但是if语句从未被评估为true。即使是简单的buttonPress事件也没有被注册。 重写的事件方法仍然没有被调用。

你尝试过这个了吗? - Marco A.
1
你能发布一下你的小部件类的头文件吗? - Gombat
@AngryDuck,什么是普通事件过滤器? - lhk
@MarcoA.,是的,那不起作用。 - lhk
1
“不可能使用eventFilter,因为它将被安装在QApplication上。” 嗯,不是这样的。可以在任何QObject上安装事件过滤器:http://doc.qt.io/qt-5/qobject.html#installEventFilter。没有必要将对象移动到应用程序范围内。 - Nicolas Holthaus
显示剩余5条评论
2个回答

3
我也需要在深层次结构中过滤鼠标事件,但是上面的答案对我来说并不完全适用。我必须进行一些小调整才能使事情正常运行。
您需要将子类化的小部件注册到QCoreApplication中,但可以轻松完成而无需遍历层次结构。在子类构造函数中放置以下行即可:
QCoreApplication::instance()->installEventFilter(this);

你的子类现在将接收所有事件,只需要过滤你需要的内容。


完整示例

头文件:

MouseMoveReaderBox : QScrollArea
{
    Q_OBJECT

public:
    explicit MouseMoveReaderBox(QWidget *parent = 0);
    ~MouseMoveReaderBox();

protected:
    bool eventFilter(QObject *obj, QEvent *event);
}

源文件:

#include "MouseMoveReaderBox"

MouseMoveReaderBox::MouseMoveReaderBox(QWidget *parent = 0)
    : QScrollArea(parent)
{
     QCoreApplicaiton::instance()->installEventFilter(this);
}

bool MouseMoveReaderBox::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::MouseMove)
    {
        // logic here...
        return true; // if you want to intercept
    }
    // Other event type checks here...
    return false; // the signal will be delivered other filters
}

希望这能有所帮助,因为我知道这个问题让我很苦恼!

2
bool someClass::eventFilter(QObject* object, QEvent* event)
{
    if(event->type() == QEvent::MouseMove)
    {
         mouseMoveFunction(static_cast<QMouseEvent*>(event))
    }
    // Repeat for other mouse events 

   // returning true blocks event returning false doesnt so if you want to block all mouse events except what your handling then return true inside each of your ifs
   return false;
}

然后在您希望应用过滤器的任何对象上安装事件过滤器,我假设您在UI类中,您可以像这样在构造函数中执行:

this->installEventFilter(this)

注:OP正在使用QCustomPlot,根据以往经验,我知道它会占用所有事件并且不会将其传递回来,所以你必须连接到它发出的鼠标点击(或任何你想要的事件)信号,包括其中的点或事件。


1
不幸的是,它并没有起作用。eventFilter方法被调用,但我无法理解何时以及为什么会调用。if语句从未评估为true(在转换处设置断点永远不会停止)。 - lhk
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - AngryDuck
我需要的事件是按钮按下和鼠标移动。而且我只需要在这个小部件上监听这些事件。我在小部件上安装了事件过滤器,并将if语句设置为接受鼠标按键按下事件。但从未返回真值。 - lhk
哦,我之前用过 QCustomPlot,我相当确定它只是消耗所有的鼠标事件,所以你需要检查是否有一些信号与事件或被点击的点一起发射,因为我相当确定它不会传递它们。 - AngryDuck
那就是解决方案。非常感谢。将其添加到您的答案中,我会接受它。 - lhk
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接