Мне нужно отобразить окна MDI, содержащие изображения, в моем приложении.Я хотел иметь возможность перетаскивать изображения с помощью правой кнопки мыши, масштабировать их с помощью колесика мыши, а также создавать на них многоугольные маски области интереса.Для этого я создал собственный класс, производный от QGraphicsView (ImageView), который переопределяет некоторые события мыши.У меня также есть класс, производный от QGraphicsPixmapItem (ImageItem) для реализации событий наведения, которые обновляют индикатор положения курсора в интерфейсе приложения.Вот схема (еще не реализует многоугольники маски):
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 () в представлении (связанном с кнопкой в графическом интерфейсе, которыйпользователь нажимает).До этого панорамирование работает нормально, курсор мыши превращается в открытую ладонь.После того, как я активирую режим AOI, курсор переходит в крест на изображении, а нажатие и перетаскивание правой кнопки перемещает представление, но не меняет курсор, как если бы курсор элемента изображения имел приоритет над курсором представления.После того, как я деактивирую режим AOI, перекрестный курсор исчезает, события наведения больше не запускаются, но на этот раз, пока панорамирование все еще работает, я застреваю с простым курсором стрелки при перетаскивании.
РЕДАКТИРОВАТЬ: По сути, это похоже на QGraphicsItem, unsetCursor () не удаляет курсор как таковой, а заменяет его на стандартную стрелку, которая является постоянной и переопределяет курсор родительского представления.
Другая проблема в том, что я не уверен, что вся обработка мыши выложена правильно.Например, я не знаю, должен ли я обрабатывать панорамирование и масштабирование в событиях мыши, переопределяющих вид, сцену или элемент изображения.Я подумал, поскольку, поскольку они являются глобальными для всего представления (которое будет содержать другие объекты в будущем), это должно принадлежать верхнему элементу - представлению.Кроме того, я не уверен, когда мне следует вызывать accept () и ignore () для событий, что это на самом деле делает, и когда я должен вызывать реализации родительских классов для событий мыши.Любое понимание будет с благодарностью.