1

在带有 C++ 的 Qt 中,我创建了一个窗口,里面有一个小 QWidget。

小QWidget每次显示一条消息QEvent::EnterQEvent::Leave或者QEvent::MouseMove被触发。

当在小 QWidget 之外按下(并按住)任何鼠标按钮,并且鼠标移动到这个小 QWidget 的顶部(按住时),QEvent::MouseMove不会为这个小 QWidget 触发。此外,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
4

1 回答 1

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 );
  }
};
于 2015-03-27T08:52:43.107 回答