我在QT中有一些怪异的行为,似乎是一个缺陷。我想知道有人是否有良好的解决方法。

我有一个弹出窗口小部件,其中包含许多按钮。用户通过按下鼠标按钮来激活弹出窗口。弹出窗口小部件调用 grabMouse 显示时。它获得了所有鼠标事件。当它滚动一个按钮时 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;
}
有帮助吗?

解决方案

我在 诺基亚DB. 。我给它大约95%的机会将其作为“按预期的工作”而关闭。

对于那些需要解决方案的人,您仍然必须使用事件过滤器并创建自己的抓取。基本上为每个孩子的小部件安装事件过滤器,并将鼠标事件传播给父母。

在上面的代码中注意,即使您不打电话,右鼠标按钮也无法工作 setDown.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top