2011-01-17 2 views
1

Qt에서 이상한 것처럼 보이는 동작이 있습니다. 아무도 좋은 해결 방법이 있는지 알고 싶습니다.Qt QAbstractButton setDown이 grabMouse와 간섭합니다.

많은 버튼이 포함 된 팝업 위젯이 있습니다. 사용자는 마우스 버튼을 눌러 팝업을 활성화합니다. 팝업 위젯은 그림과 같이 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을 호출하지 않아도 마우스 오른쪽 버튼이 작동하지 않습니다.