LINUX.ORG.RU

Qt QGraphicsView::map(To|From)Scene

 ,


0

1

Здравствуйте, объясните пожалуйста, что я не так делаю. Мне нужно получить координаты сцены для объектов. Грубо говоря, чтобы разные объекты имели одинаковые координаты. Пока если я создаю объект в координатах (300,300), то при помещении в координату (0,0) функция pos() возвращает координаты (-300, -300). Пользуюсь классом, наследуемым от QGraphicsItem. Пробовал сделать так:

 QPointF p=ui->gvScene->mapToScene(obj->pos().x(), obj->pos().y())        ;
    qDebug()<<p.x()<<p.y();
где ui->gvScene - GraphicsVew на котором отрисовываются объекты. Однако такой способ по-прежнему выдает (-300,-300) в нулевой координате. Причем, если я создам объект в координатах(100,100), то pos вернет соответственно (-100,-100)

Непонятно что я упустил. И еще не совсем понятно, почему QGraphicsItem тоже имеет методы map(To|From)Scene. В чем разница вызова этих методов для GraphicsView или для GraphicsItem?

Извините пожалуйста за ламерские вопросы

Не очень понятно, что ты хочешь сделать. Разные объекты имели одинаковые координаты в пространстве сцены? Поместить их в одну точку?

Сцена и каждый объект имеет по своему собственному координатному пространству. В этом пространстве верхний левый угол объекта (пусть это будет прямоугольник) = (0, 0). Но при этом объект принадлежит сцене (или другому объекту, они могут быть вложенными), у которого своё координатное пространство. И объект имеет положение в этом _родительском_ пространстве = pos().

item.mapToScene() берёт точку в координатах _объекта_ и превращает в координаты _родителя_. Например, есть рыба с pos() = (300, 300) - в координатах сцены. У рыбы есть глаз в точке (10, 10) - координаты рыбы, относительные. fish.mapToScene(10, 10) вернёт (310, 310) - абсолютно положение глаза.

scene.mapToScene() работает с окном вывода. Точку окна вывода (реальную точку экрана) переводит в координаты сцены. Например, есть аквариум 1000х1000, а экран всего 320х200. Сдвигаем окно вывода так, чтобы он показывал прямоугольник с лево-верхним углом = (100, 100), ширина = (320, 200), соотв. право-нижний угол = (420, 300). На экране рыба в точке _окна_ = (32, 32). Хотим узнать её координаты на сцене - scene.mapToScene(100, 100) = (100, 100) + (32, 32) = (132, 132). Смещение окна вывода и смещение рыбы относительно лево-верхнего угла _экрана_.

В твоём случае, соответственно, item.pos() уже хранит приведённые к сценарной системе координаты объектов, нет нужды их мапить вручную.

И ещё, pos() возвращает координаты в пересчёте на систему родителя - а это может быть и не сцена, а другой объект. Для сцены напрямую есть scenePos().

schizoid ★★★ ()
Ответ на: комментарий от schizoid

Спасибо за ответ! Попытаюсь пояснить что мне нужно - я пишу небольшой редактор. С-но пользователь может перемещать различные объекты по сцене и задавать их координаты через таблицу. По аналогии, как в Qt Creator свойства каждого элемента можно изменить через таблицу, в которой указаны имя объекта, координаты, размер, стиль и т.п.

Мне нужно, чтобы любой объект, независимо от его начальных координат, на краю сцены имел координату (0,0), т.к. в дальнейшем он будет сохранять эти координаты в формат уровня, который будет парситься другой программой.

Пока же получается так: позиция элемента зависит от начальных координат - например, если мы создали объект в координатах (500,500), то при перемещении его в точку (0,0) он имеет координаты (-500, -500), что мне совершенно ненужно.

Пока все работает таким образом - при изменении позиции объект испускает сигнал, который ловит главное окно и выводит его текущие координаты. В дальнейшем в слоте главного окна будет также изменяться координаты в таблицы. Но пока мне достаточно отладки. В сигнале я передаю указатель на графический объект. получается что-то вроде:

//посыл сигнала:
QVariant EditorMovingObject::itemChange(GraphicsItemChange change,
                                        const QVariant &value)//если объект изменился
{
    if((change==QGraphicsItem::ItemPositionHasChanged)&&(isSelected()))//
    {
    emit signal_itemChanged(this, 1);//если изменилась позиция объекта, шлем сигнал
    }
    return value;
}

//слот главного окна:
void MainWindow::slot_itemChanged(EditorMovingObject *obj, int type)
{
    QPointF p=ui->gvScene->mapToScene(obj->scenePos().x(), obj->scenePos().y())        ;
    qDebug()<<p.x()<<p.y();
}

Я изменил pos() на scenePos(), однако это не привело ни к каким результатам. Если я создаю объект в координатах, неравных нулю, то в дальнейшем он будет в нулевой точке иметь отрицательные координаты. И чем больше была начальная координата, тем больше будут отрицатетльные. Мне же нужно, чтобы они были равны нулю, т.е. соответствовали координатам сцены и всегда в одинаковой точке на экране были одинаковыми для всех объектов, независимо от начальных координат при создании объектов.

gwyllum ()
Ответ на: комментарий от gwyllum

Как ты создаёшь объект? И что за объект? Для scene.addRect(), например, указано, что прямоугольник создастся в координатах объекта. То есть, addRect(10, 10, 32, 32) создаст объект (пустой), у которого есть прямоугольник в относительных координатах (10, 10). И при установке прямоугольника в (0, 0) позиция самого объекта окажется в (-10, -10). Что-то подобное, видимо, и происходит в твоём случае.

Как происходит установка координат в твоём случае?

    QGraphicsItem * item = new QGraphicsRectItem();
    qDebug() << item->pos();
    scene.addItem(item);
    item->setPos(10, 10);
    qDebug() << item->pos();
QPointF(0, 0) 
QPointF(10, 10)

schizoid ★★★ ()
Ответ на: комментарий от schizoid

Спасибо за ответ! Вы натолкнули на корень проблемы - я создавал объект так:

m_shape.addRect(x, y,width, height);
изменил на:
    m_shape.addRect(0, 0,width, height);
    setPos(x,y);
И все заработало как нужно.

gwyllum ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.