Question

J'ai un comportement bizarre dans Qt qui semble comme un défaut. Je voudrais savoir si quelqu'un a une bonne solution.

J'ai un widget pop-up qui contient beaucoup de boutons en elle. L'utilisateur active le menu contextuel en appuyant sur le bouton de la souris vers le bas. Le widget de pop-up appelle grabMouse quand indiqué. Il obtient tous les événements de la souris. Comme il roule sur un bouton, il appelle setDown(true) sur le bouton. Maintenant, cependant, lorsque le bouton de la souris est relâché le menu contextuel widget ne reçoit pas le mouseReleaseEvent, qui va au bouton.

C'est, appelant setDown(true) sur un bouton provoque le bouton pour voler des événements de souris, sans passer par le grabMouse dans le widget popup.

Je l'ai regardé le code source pour setDown mais je ne vois rien là que ferait directement. Je remarque cependant aussi que, parfois, un bouton devient un événement de vol stationnaire, parfois pas. Je suppose que ce serait jamais ces événements lorsque la souris est saisi.

//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;
}
Était-ce utile?

La solution

Je l'ai inscrit le problème au Nokia DB . Je lui donne une chance sur 95% qu'ils ferment comme « fonctionne comme prévu ».

Pour ceux qui ont besoin d'une solution, vous devez néanmoins utiliser des filtres d'événements et créez votre propre accaparement. Fondamentalement, installer un filtre d'événements pour chaque widget enfant et propager les événements de souris au parent.

Note dans le code ci-dessus que le bouton droit de la souris ne fonctionne pas même si vous ne l'appelez pas setDown.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top