[英]Qt QAbstractButton setDown interferes with grabMouse
我在Qt中有一些奇怪的行为,似乎是一个缺陷。 我想知道是否有人有很好的解决方法。
我有一个弹出窗口小部件,其中包含许多按钮。 用户通过按下鼠标按钮来激活弹出窗口。 显示时,弹出窗口小部件将调用grabMouse
。 它获取所有鼠标事件。 当setDown(true)
悬停在按钮上时,它将在按钮上调用setDown(true)
。 但是,现在释放鼠标按钮时,弹出窗口小部件没有获取mouseReleaseEvent
,而是转到该按钮。
也就是说,在按钮上调用setDown(true)
会导致该按钮窃取鼠标事件,从而绕过弹出窗口小部件中的grabMouse
。
我已经看过setDown
的源代码,但是看不到有任何可以直接执行的内容。 但是我也注意到有时按钮会发生悬停事件,有时却不会。 我想当鼠标被抓住时它将永远不会发生那些事件。
//g++ -o grab_lost grab_lost.cpp -lQtCore -lQtGui -I /usr/include/qt4/ -I /usr/include/qt4/QtCore -I /usr/include/qt4/QtGui
/**
Demonstrates the defect of losing the mouse. Run the program and:
1. Press mouse anywhere
2. release in purple block (not on X)
3. Release message written (GrabLost receives the mouseReleaseEvent)
For defect:
1. Pree mouse anywhere
2. Release inside the X button
3. button is clicked, no release message (GrabLost does not get the mouseReleaseEvent)
*/
#include <QWidget>
#include <QPushButton>
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
class GrabLost : public QWidget
{
QPushButton * btn;
public:
GrabLost( QWidget * parent = 0)
: QWidget( parent, Qt::Popup )
{
btn = new QPushButton( "X", this );
setMouseTracking( true );
}
protected:
void showEvent( QShowEvent * ev )
{
QWidget::showEvent( ev );
grabMouse();
}
void closeEvent( QCloseEvent * ev )
{
releaseMouse();
QWidget::closeEvent( ev );
}
void hideEvent( QHideEvent * ev )
{
releaseMouse();
QWidget::hideEvent( ev );
}
void mouseReleaseEvent( QMouseEvent * ev )
{
qDebug( "mouseRelease" );
close();
}
void mouseMoveEvent( QMouseEvent * ev )
{
QWidget * w = childAt( ev->pos() );
bool ours = dynamic_cast<QPushButton*>( w ) == btn;
btn->setDown( ours );
}
void paintEvent( QPaintEvent * ev )
{
//just to show where the widget is
QPainter pt( this );
pt.setPen( QColor( 0,0,0 ) );
pt.setBrush( QColor( 128,0,128) );
pt.drawRect( 0, 0, size().width(), size().height() );
}
};
class GrabMe : public QWidget
{
protected:
void mousePressEvent( QMouseEvent * ev )
{
GrabLost * gl = new GrabLost();
gl->resize( 100, 100 );
QPoint at( mapToGlobal( ev->pos() ) );
gl->move( at.x() - 50, at.y() - 50 );
gl->show();
}
};
int main( int argc, char** argv )
{
QApplication app( argc, argv );
GrabMe * gm = new GrabMe();
gm->move( 100, 100 );
gm->resize( 300, 300 );
gm->show();
app.exec();
return 0;
}
我已经在诺基亚数据库中输入了缺陷。 我给了他们95%的机会,让他们按照“预期的工作方式”将其关闭。
对于那些需要解决方案的人,您将不得不使用事件过滤器并创建自己的抓取工具。 基本上为每个子窗口小部件安装一个事件过滤器,并将鼠标事件传播到父窗口。
请注意,在上面的代码中,即使不调用setDown
鼠标右键也setDown
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.