Qt QAbstractButton setDown взаимодействует с grabMouse - PullRequest
1 голос
/ 17 января 2011

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

0 голосов
/ 18 января 2011

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

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

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

...