在带有C ++的Qt中,我创建了一个带有小QWidget的窗口。
每次触发QEvent::Enter
,QEvent::Leave
或QEvent::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 );
}
};