Добрый день.
Мне потребовалось перетаскивать графические элементы не по двум координатам (как это делается по умолчанию, например, в примере chip), а только по одной (двигаю флажки вдоль оси OX). Я перекрыл обработку событий от мыши, в первую очередь, mouseMoveEvent. Вот слегка почищенный код класса Flag (наследника QGraphicsItem):
C
Flag::Flag(const QString& name, const QColor& color):
_name(name), _color(color)
{
setFlags(ItemIsSelectable | ItemIsMovable);
setAcceptHoverEvents(true);
}
void Flag::paint(QPainter *p, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
int height = FLAG_HEIGHT;
int dX = -FLAG_WIDTH;
p->setPen(_color);
p->drawLine(0, 1, 0, FLAG_HEIGHT);
p->drawLine(0, FLAG_HEIGHT, dX, FLAG_HEIGHT-FLAG_SUBHEIGHT/2);
p->drawLine(dX, FLAG_HEIGHT-FLAG_SUBHEIGHT/2, 0, FLAG_HEIGHT-FLAG_SUBHEIGHT);
}
QRectF Flag::boundingRect() const
{
return QRectF(-FLAG_WIDTH+1, 2, FLAG_WIDTH, FLAG_HEIGHT);
}
void Flag::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
update();
}
void Flag::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// Set new position
int newX = event->scenePos().x();
setPos(newX, 1);
}
void Flag::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
}
Вот фрагменты конструктора главного окна:
C
view = new QGraphicsView(ui->frame);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(view);
ui->frame->setLayout(layout);
...
QGraphicsScene* scene = new QGraphicsScene;
view->setScene(scene);
...
Flag* flag = new Flag("magenta", Qt::magenta);
view->scene()->addItem(flag);
flag = new Flag("black", Qt::black);
view->scene()->addItem(flag);
flag->setPos(80, 0);
При запуске программы на экране появляются два флажка. Я действительно могу их перетаскивать мышью, но при этом второй флаг "съезжает" в другую сторону. Судя по более сложному примеру, в котором были не только флажки, сдвигается вся сцена.
Насколько я могу судить, это связано с тем, что в начале работы у сцены нулевая ширина, по мере вызова setPos для элементов она расширяется, и Qt пытается его отцентровать относительно QGrapgicsView, через который идёт отображение.
Я сделал временное решение. В том же конструкторе главного окна сделал принудительную установку размера сцены по виджету:
C
int w = view->width();
int h = view->height();
scene->setSceneRect(-w/2, -h/2, w, h);
Вроде бы проблема ушла. Но мне интуиция подсказывает, что это костыль, который может к тому же отказать при каком-нибудь "хитром" ресайзе, хотя пока я такого не добился.
Есть ли более нормальное решение? Например, как-то отключить эту автоматическую центровку вообще...
Проблема проверена на Qt 4.6 и 4.8.4 в Windows и Linux.
Спасибо.