Qt QAbstractButton setDown взаимодействует с grabMouse

У меня странное поведение в 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;
}

1 ответ

Решение

Я ввел дефект в базе данных Nokia. Я даю ему около 95% вероятности, что они закроют его, как "работает по назначению".

Тем, кто нуждается в решении, тем не менее, вам придется использовать фильтры событий и создать свой собственный захват. В основном установите фильтр событий для каждого дочернего виджета и распространите события мыши на родительский виджет.

Обратите внимание на приведенный выше код, что правая кнопка мыши не работает, даже если вы не звоните setDown,

Другие вопросы по тегам