2011-03-10 4 views
0

내 응용 프로그램에 이미지가 포함 된 MDI 창을 표시해야합니다. 마우스 오른쪽 버튼을 사용하여 이미지를 드래그하여 스크롤하고, 마우스 휠을 사용하여 이미지를 확대하고, 다각형 모양의 관심 영역 마스크를 만들 수 있기를 원했습니다. 이를 위해 일부 마우스 이벤트를 다시 구현하는 커스텀 QGraphicsView 파생 클래스 (ImageView)를 만들었습니다. 또한 응용 프로그램의 인터페이스에서 커서 픽셀 위치 표시기를 업데이트하는 호버 이벤트를 구현하기위한 QGraphicsPixmapItem 파생 클래스 (ImageItem)가 있습니다. 여기 개요 (아직 마스크 다각형을 구현하지 않습니다는)입니다 :Qt에서 대화 형 QGraphicsView를 구현할 때 마우스 커서를 변경하는 데 문제가있는 이유는 무엇입니까?

class ImageView : public QGraphicsView 
{ 
    Q_OBJECT 
public: 
    ImageView(QWidget *parent) : QGraphicsView(parent), _pan(false), _panStartX(0), _panStartY(0), 
     _scale(1.2), _scene(NULL), _imgItem(NULL) 
    { 
     _scene = new QGraphicsScene(this); 
     _scene->setBackgroundBrush(Qt::lightGray); 
     setScene(_scene); 
     _imgItem = new ImageItem(this); 
     _scene->addItem(_imgItem); 
    } 

    void showImage(const QString &path) 
    { 
     _imgItem->loadImage(path); 
     setSceneRect(0, 0, _imgItem->imageWidth(), _imgItem->imageHeight()); 
    } 

    void startAoi(AoiType type) 
    { 
     _imgItem->setAcceptHoverEvents(true); 
     _imgItem->setCursor(Qt::CrossCursor); 
     // explicit mouse tracking enable isn't necessary 
    } 

    void stopAoi() 
    { 
     _imgItem->unsetCursor(); 
     _imgItem->setAcceptHoverEvents(false); 
    } 

public slots: 
    void zoomIn() { scale(_scale, _scale); } 
    void zoomOut() { scale(1/_scale, 1/_scale); } 

protected: 
    void ImageView::mousePressEvent(QMouseEvent *event) 
    { 
     // enter pan mode; set flag, change cursor and store start position 
     if (event->button() == Qt::RightButton) 
     { 
      _pan = true; 
      _panStartX = event->x(); 
      _panStartY = event->y(); 
      setCursor(Qt::OpenHandCursor); 
      // accept the event and skip the default implementation? 
      event->accept(); 
      return; 
     } 

     // should do event accept here? 
     event->ignore(); 
    } 

    void ImageView::mouseReleaseEvent(QMouseEvent *event) 
    { 
     // leave pan mode on right button release; clear flag and restore cursor 
     if (_pan && event->button() == Qt::RightButton) 
     { 
      _pan = false; 
      unsetCursor(); 
      event->accept(); 
      return; 
     } 

     // in the future, left clicks will add vertices to a mask polygon 
     event->ignore() // ? 
    } 

    void ImageView::mouseMoveEvent(QMouseEvent *event) 
    { 
     // pan-mode move; scroll image by appropriate amount 
     if (_pan) 
     { 
      scrollBy(_panStartX - event->x(), _panStartY - event->y()); 
      _panStartX = event->x(); 
      _panStartY = event->y(); 
      event->accept(); 
      return; 
     } 

     // generic mouse move, hover events won't occur otherwise. 
     QGraphicsView::mouseMoveEvent(event); 
     // need to accept or ignore afterwards? 
    } 

    void ImageView::wheelEvent(QWheelEvent *event) 
    { 
     // disallow zooming while panning 
     if (_pan) 
     { 
      event->ignore(); 
      return; 
     } 

     // handle mouse wheel zoom 
     // perform scaling 
     if (event->delta() > 0) zoomIn(); 
     else zoomOut(); 
     event->accept(); 
     return; 
    } 


    bool _pan; 
    int _panStartX, _panStartY; 
    const qreal _scale; 
    QGraphicsScene *_scene; 
    ImageItem *_imgItem; 
}; 

class ImageItem : public QGraphicsPixmapItem 
{ 
public: 
    ImageItem(ImageView *view) : QGraphicsPixmapItem() 
    { 
    } 

    void loadImage(const QString &path) 
    { 
     _pixmap.load(path); 
     setPixmap(_pixmap); 
    } 

protected: 
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event) 
    { 
     // update label with position in GUI here 
    } 

    QPixmap _pixmap; 
}; 

내 첫 번째 문제는 모든 것을 내가보기에 startAoi()를 활성화하기 전에 (GUI의 버튼에 연결되어 잘 작동되는 사용자 프레스). 그 전에 마우스 커서가 열린 손으로 바뀌면서 패닝이 제대로 작동합니다. AOI 모드를 활성화하면 이미지 위에 커서가 십자 모양으로 바뀌고 오른쪽 버튼을 누르고 드래그하면보기가 이동되지만 이미지 항목의 커서가보기의 커서보다 우선하는 것처럼 커서는 바뀌지 않습니다. AOI 모드를 비활성화하면 십자형 커서가 사라지고 호버 이벤트가 더 이상 트리거되지 않지만 이번에는 팬이 작동하는 동안 드래그하는 동안 일반 화살표 커서가 붙어 있습니다.

편집 :는 기본적으로, 그것은 QGraphicsItem, unsetCursor() 그 자체로 커서를 삭제하지 않습니다에 대한처럼 보이는 것이 아니라 지속적이고 부모 뷰의 커서를 무시 표준 화살표로 변경합니다.

다른 문제는 전체 마우스 처리가 올바르게 배치되어 있는지 잘 모르겠습니다. 예를 들어,보기, 장면 또는 이미지 항목의 마우스 이벤트 재정의에서 이동 및 확대/축소를 처리해야하는지 여부는 알 수 없습니다. 나는 (이후에 다른 객체를 포함 할 것입니다) 전체보기에 대한 것이기 때문에 이것이 최상위 항목 (보기)에 속해야한다고 생각했습니다. 또한 이벤트에 accept() 및 ignore()를 호출해야하는지, 이것이 실제로 무엇을하는지, 그리고 부모 클래스의 마우스 이벤트 구현을 호출해야하는지 알 수 없습니다. 어떤 통찰력이라도 대단히 감사하겠습니다.

답변

1

몇 달 전에 유사한 이미지 조작 응용 프로그램을 만들었습니다 : 이미지 드래그, 확대/축소 및 QGraphicsView에서 특정 항목을 그리는 (추가) 다른 사용자 정의 도구. unsetCursor()가 아닌 setCursor() 함수 만 사용했습니다.

저는 타이머를 만들었고 GraphicsView 하위 클래스에 저장된 사용자 정의 "도구 유형"플래그에 따라 timer-event 함수 내에 커서 모양을 설정하고 키보드의 현재 상태 인 & 마우스를 고려했습니다. 더 편리하다고 생각합니다.

a) 사용자가 마우스를 움직이거나 특정 개체 (예 : 마우스)를 움직이지 않아도 커서 모양을 설정할 수 있습니다. "확대/축소 도구"가 선택되면 커서를 (+) [확대 커서]로 설정할 수 있습니다. 사용자가 Ctrl 키를 누른 채로 있으면 커서를 (-) [축소 커서]로 설정할 수 있습니다.

b) 커서 상태를 저장할 필요가 없습니다. 올바른 커서 모양 만 설정하면됩니다. 현재 선택된 도구와 마우스/키보드 상태에 따라 다릅니다.

C)이 커서 모양이 신속하게 모든 키보드/마우스/공구 변경 이벤트 내가이 타이머 아이디어는 모든 커서 모양과 관련된 문제를 극복하는 데 도움이 될 수 있습니다 희망

에 응답 할 수 있도록하는 가장 쉬운 방법입니다. 30msec 간격의 타이머로 정상적으로 작동합니다.이 버그 공격 같은

관련 문제