Domanda

ho qualche strano comportamento in Qt che sembra un difetto. Mi piacerebbe sapere se qualcuno ha una buona soluzione.

Ho un widget a comparsa che contiene molti pulsanti in esso. L'utente attiva il popup premendo il pulsante del mouse. Il pop-up widget di chiama grabMouse quando indicato. Ottiene tutti gli eventi del mouse. Come si rotola su un pulsante che chiama setDown(true) sul pulsante. Ora invece, quando il pulsante del mouse viene rilasciato il popup widget di non ottiene il mouseReleaseEvent, che va al pulsante.

Cioè, chiamando setDown(true) su un pulsante fa sì che il pulsante di rubare gli eventi del mouse, bypassando il grabMouse nel widget a comparsa.

Ho guardato il codice sorgente per setDown ma non riesco a vedere nulla che avrebbe farlo direttamente. Ho anche notato, tuttavia, che a volte un tasto diventa un evento hover, a volte no. Vorrei assumere non sarebbe mai ottenere quegli eventi quando il mouse viene afferrato.

//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;
}
È stato utile?

Soluzione

Ho inserito il difetto al Nokia DB . Sto dando una probabilità circa il 95% che si chiudono come "funziona come previsto".

Per quelli di voi che hanno bisogno di una soluzione comunque dovrete usare filtri eventi e creare il proprio grabbing. Fondamentalmente installare un filtro eventi per ogni widget figlio e propagare gli eventi del mouse al genitore.

Nota nel codice sopra che il tasto destro del mouse non funziona, anche se non si chiama setDown.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top