使用Pressed按钮输入时,QWidget不会触发QEvent :: MouseMove

时间:2015-03-27 06:51:57

标签: c++ qt mousemove qevent

在Qt with C ++中,我创建了一个内部有一个小QWidget的窗口。

每次触发QEvent::EnterQEvent::LeaveQEvent::MouseMove时,小型QWidget都会显示一条消息。

当在小QWidget外面按下(并保持)任何鼠标按钮时,鼠标移动到这个小QWidget的顶部(在按住时),这个小QWidget不会触发QEvent::MouseMove。此外,释放鼠标按钮后QEvent::Enter被推迟。

在相反的情况下:当在小QWidget上按下鼠标(并且已经掌握),然后将鼠标移到外面时,QEvent::Leave被推迟到鼠标按钮释放后。

是否有任何解决方案可以随时检索QEvent::MouseMove,即使鼠标按钮已被固定?

其他数据:是的,setMouseTracking(true)已设置。

测试示例:

窗口小部件:

#ifndef MYWIDGET_HPP
#define MYWIDGET_HPP

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QEvent>
#include <QDebug>

class MyWidget: public QWidget
{
    Q_OBJECT
public:
    MyWidget( QWidget* parent=nullptr ): QWidget(parent)
    {
        setMouseTracking(true);
    }
protected:

    // Paint for styling
    void paintEvent(QPaintEvent *)
    {
        // Needed to allow stylesheet.
        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }

    // Show Enter and Leave event for debugging purpose
    bool event( QEvent *e)
    {
        static int counting=0;
        if (e->type() ==QEvent::Enter)
        {
            qDebug() << counting++ << " Enter: " << this->objectName();
        }
        if (e->type() ==QEvent::Leave)
        {
            qDebug() << counting++ << " Leave: " << this->objectName();
        }

        if (e->type() ==QEvent::MouseMove)
        {
            qDebug() << counting++ << " Move: " << this->objectName();
        }
        return QWidget::event(e);
    }

};

#endif // MYWIDGET_HPP

主要

#include <QApplication>

#include <QDebug>
#include <QWidget>
#include <QTimer>

#include "Testing.hpp"


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // Create a main window
    QWidget main;
    main.setWindowTitle("Cursor blocked for 5s - wait and see");
    main.resize(500, 200);
    main.move(200, 200);

    // Create a MyWidget
    MyWidget sub(&main);
    sub.setObjectName("sub");
    sub.resize(50, 50);
    sub.move(50, 50);

    // Style the button with a hover
    main.setStyleSheet
    (
        "QWidget#sub{background-color: rgba(0,0,128,0.5);}"
        "QWidget#sub:hover{background-color: rgba(128,0,0,0.5);}"
    );

    // Show the window
    main.show();

    return a.exec();

}

项目

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

SOURCES +=\
    main.cpp

HEADERS  +=\
    Testing.hpp

RESOURCES +=\

CONFIG += c++11 -Wall

TARGET = Testing
TEMPLATE = app

1 个答案:

答案 0 :(得分:0)

这是标准行为。当您按下鼠标按钮时,小部件开始抓取它(拨打QWidget::grabMouse)。我认为当你需要全局跟踪鼠标时,你应该重新设计你的行为,或解释一些真实的用例。

如果您确实需要跟踪鼠标,可以使用事件过滤器。

伪代码(不带支票):

QWidget *otherWidget = /*...*/;
QWidget *myWidget  = /*...*/;
otherWidget->installEventFilter( myWidget );
// you need to install filter on each widget,
// that you want to track.
// Care with performance

MyWidget : QWidget
{
  void handleMouseMove( QPoint pos ) { /*...you code...*/ }

  void mouseMove( QMouseEvent *e ) override;
  {
    handleMouseMove( e->pos() );
    QWidget::mouseMove( e );
  }

  bool eventFilter( QObject *obj, QEvent *e )
  {
    auto srcWidget = qobject_cast< QWidget * >( obj );
    switch ( e->type() )
    {
    case QEvent::MouseMove:
      {
        auto me = static_cast< QMouseEvent * >( e );
        auto globalPos = srcWidget->mapToGlobal( me->pos() );
        auto localPos = this->mapFromGlobal( globalPos ); // Possible, you need to invalidate that poing belongs to widget
        handleMouseMove( localPos );
      }
      break;
    };
    return QWidget::eventFilter( obj, e );
  }
};