Вопрос

У меня есть какое -то странное поведение в 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;
}
Это было полезно?

Решение

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top