2011-01-17 2 views
1

У меня есть странное поведение в Qt, которое кажется дефектом. Я хотел бы знать, есть ли у кого-то хорошее обходное решение.Qt QAbstractButton setDown вмешивается в grabMouse

У меня есть виджет всплывающих окон, который содержит в нем много кнопок. Пользователь активирует всплывающее окно, нажав кнопку мыши вниз. Виджет popup вызывает 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; 
} 

ответ

0

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

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

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