내 응용 프로그램에 이미지가 포함 된 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()를 호출해야하는지, 이것이 실제로 무엇을하는지, 그리고 부모 클래스의 마우스 이벤트 구현을 호출해야하는지 알 수 없습니다. 어떤 통찰력이라도 대단히 감사하겠습니다.