简体   繁体   English

Qt QAbstractButton setDown干扰了grabMouse

[英]Qt QAbstractButton setDown interferes with grabMouse

I have some weird behaviour in Qt that seems like a defect. 我在Qt中有一些奇怪的行为,似乎是一个缺陷。 I'd like to know if anybody has a good workaround. 我想知道是否有人有很好的解决方法。

I have a popup widget that contains many buttons in it. 我有一个弹出窗口小部件,其中包含许多按钮。 The user activates the popup by pressing the mouse button down. 用户通过按下鼠标按钮来激活弹出窗口。 The popup widget calls grabMouse when shown. 显示时,弹出窗口小部件将调用grabMouse It gets all the mouse events. 它获取所有鼠标事件。 As it rolls over a button it calls setDown(true) on the button. setDown(true)悬停在按钮上时,它将在按钮上调用setDown(true) Now however, when the mouse button is released the popup widget does not get the mouseReleaseEvent , that goes to the button. 但是,现在释放鼠标按钮时,弹出窗口小部件没有获取mouseReleaseEvent ,而是转到该按钮。

That is, calling setDown(true) on a button causes the button to steal mouse events, bypassing the grabMouse in the popup widget. 也就是说,在按钮上调用setDown(true)会导致该按钮窃取鼠标事件,从而绕过弹出窗口小部件中的grabMouse

I've looked at the source code for setDown but I can't see anything there that would do it directly. 我已经看过setDown的源代码,但是看不到有任何可以直接执行的内容。 I also notice however that sometimes a button gets a hover event, sometimes not. 但是我也注意到有时按钮会发生悬停事件,有时却不会。 I would assume it would never get those events when the mouse is grabbed. 我想当鼠标被抓住时它将永远不会发生那些事件。

//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;
}

I've entered the defect at the Nokia DB . 我已经在诺基亚数据库中输入了缺陷。 I'm giving it about a 95% chance that they close it as "works as intended". 我给了他们95%的机会,让他们按照“预期的工作方式”将其关闭。

For those of you that need a solution nonetheless you'll have to use event filters and create your own grabbing. 对于那些需要解决方案的人,您将不得不使用事件过滤器并创建自己的抓取工具。 Basically install an event filter for every child widget and propagate the mouse events to the parent. 基本上为每个子窗口小部件安装一个事件过滤器,并将鼠标事件传播到父窗口。

Note in the above code that the right mouse button doesn't work even if you don't call setDown . 请注意,在上面的代码中,即使不调用setDown鼠标右键也setDown

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM