Создание подкласса QGraphicsView и настройка drawBackground

Я пытаюсь сделать функцию, похожую на impoly (из Matlab) в Qt. Прямо сейчас у меня есть подкласс QGraphicsView, и я установил виртуальную функцию «drawBackground» как:

void roiwindow::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->save();
painter->drawImage(rect, *refimage);
painter->restore();
}

Это прекрасно работает и в основном именно то, что я хочу, что касается фонового слоя. Теперь я пытаюсь добавить круги, которые в конечном итоге станут узлами многоугольника. Я сделал это, используя:

QGraphicsView *view = new QGraphicsView(this);
view->show();
QGraphicsEllipseItem *e1;
e1 = this->addEllipse(20, 20, 30, 30, QColor(0, 0, 0), Qt::white);
e1->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsMovable);

Это то, чего я хочу. Но есть проблема, что когда я щелкаю и перетаскиваю эллипсы, фон эллипса представляет собой уменьшенную версию *refimage... Это оставляет своего рода полосу на экране, но она исчезает, когда я нажимаю на другое окно или свернуть окно. QGraphicsItem также вызывает drawBackground? Если это так, кажется, что это вызывается только при перетаскивании элемента. Любые предложения о том, как я могу кодировать это лучше? Спасибо.


person Justin    schedule 22.05.2012    source источник
comment
Просто добавил оператор printf, и при перетаскивании элемента вызывается функция недостатка земли...   -  person Justin    schedule 23.05.2012
comment
Откуда refimage?   -  person KcFnMi    schedule 09.09.2019


Ответы (2)


Полосы возникают из-за того, что вы, вероятно, установили для QGraphicsView значение по умолчанию обновление окна просмотра режим, то есть QGraphicsView::MinimalViewportUpdate. В этом случае вам нужно QGraphicsView::FullViewportUpdate. Причина в том, что когда вы перемещаете элементы, фон позади них должен быть перерисован, но когда вы установили MinimalViewportUpdate, будут перерисованы только элементы (если нет полного обновления области просмотра, например, из-за сворачивания/разворачивания окна) .

person Anthony    schedule 22.05.2012
comment
Это было бы возможно, но, вероятно, медленно, так как при каждом обновлении все изображение будет масштабироваться и рисоваться. - person leemes; 23.05.2012
comment
@leemes Если в сцене много элементов, это не обязательно будет медленнее. Если в сцене мало объектов, разница в скорости, вероятно, будет незначительной, если не совсем незаметной. - person Anthony; 23.05.2012
comment
Представьте себе сцену размером 1k x 1k пикселей с большим количеством элементов. Теперь он перемещает элемент размером 20 x 20 пикселей на 5 пикселей => перерисовка 1M пикселей против 100 пикселей масштабированного фонового изображения составляет 10000 плюс перерисовка других элементов. Для плавного перемещения перетаскиваемого элемента это может быть проблематичным. Но я думаю, что это зависит от случая... - person leemes; 23.05.2012
comment
@leemes ОП пытается воссоздать имполи из MATLAB, в котором есть не только узлы, но и соединительные звенья. По моему опыту, ссылки, как правило, имеют большие ограничивающие прямоугольники (потому что они обычно диагональные), если только вы не возитесь с ограничивающей областью, что дорого обходится. Так что я думаю маловероятно, что сцена будет содержать только крошечные предметы. - person Anthony; 23.05.2012
comment
Это решило проблему, с которой я столкнулся, и позволило мне сохранить масштабированное фоновое изображение. Я буду возиться с этим, чтобы убедиться, что нет проблем с производительностью. Спасибо за ответ. - person Justin; 23.05.2012
comment
@user1346994 user1346994 Если это слишком медленно, попробуйте сохранить масштабированную копию фонового изображения, которую вы обновляете всякий раз, когда изменяется размер представления (переопределите QGraphicsView::resizeEvent). Затем нарисуйте это масштабированное изображение в drawBackground. - person leemes; 23.05.2012
comment
Хорошая идея. Я реализую это для больших изображений. Спасибо! - person Justin; 23.05.2012
comment
См. Мой связанный вопрос для удобного трюка, если ваш фон представляет собой повторяющееся изображение на основе плитки. - person paulm; 19.12.2012

QGraphicsView::drawBackground вызывается всякий раз, когда что-то в графическом представлении необходимо перерисовать. Это что-то может быть меньше всего представления для лучшей производительности.

Пример: когда у вас есть прямоугольный элемент, скажем, 50 x 50 пикселей, в пределах большей сцены/представления, и вы перемещаете этот прямоугольник на 20 пикселей вправо, только область, покрытая предыдущей + новой позицией элемента (70 x 50 пикселей) перерисовывается (поскольку это область, которая меняется).

В вашей новой реализации drawBackground вы говорите:

painter->drawImage(rect, *refimage);

который на самом деле рисует изображение в размере обновляемой области, а не общего размера представления.

Чтобы каждый раз рисовать изображение в одной и той же позиции и одного размера, вы можете использовать постоянную позицию (например, начало координат) и не изменять размер изображения:

painter->drawImage(0, 0, *refimage);

или вы можете использовать всю область сцены:

painter->drawImage(sceneRect(), *refimage);

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

scene()->setSceneRect(0, 0, 800, 800);

См. документацию: QGraphicsView::sceneRect и QGraphicsScene::sceneRect

person leemes    schedule 22.05.2012
comment
Спасибо за ответ. Я попробовал это, и это прекрасно работает. Единственная проблема в том, что фон не масштабируется до размера окна. Я бы хотел, чтобы размер окна можно было изменять, но если это приведет к проблемам в будущем, я могу вернуться к этому решению. Спасибо за ответ. - person Justin; 23.05.2012
comment
Вы хотите, чтобы ваш фон был статичным и независимым от прокрутки, то есть всегда отображался в одной и той же позиции экрана (и в размере видимого вида), а не в позиции сцены (и в размере сцены)? Если да, то это не правильное решение. - person leemes; 23.05.2012