在带有C ++的Qt中,我创建了一个带有小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

最佳答案

这是标准行为。当您按下鼠标按钮时,小部件开始抓取它(调用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 );
  }
};

10-07 23:23