#c #qt #qt4 #qgraphicsview #qgraphicsitem
#c #qt #qt4 #qgraphicsview #qgraphicsitem
Вопрос:
Я пытаюсь создать, QGraphicsView
который позволит кому-то масштабировать текущее QGraphicsItem
, чтобы соответствовать размеру QGraphicsView
окна.
Я переопределил QGraphicsItem
для создания пользовательской версии, и я внедрил некоторые методы, чтобы он знал, насколько он был масштабирован (который всегда пропорционален оригиналу, поэтому существует только один масштабный коэффициент — одинаковый для ширины и высоты).
Итак, в scaleFactor
установщике у меня есть следующее:
void ImagePixmapItem::setScaleFactor(float sf){
scaleFactor = sf;
this->boundingRect().setWidth(this->boundingRect().width()*scaleFactor);
this->boundingRect().setHeight(this->boundingRect().height()*scaleFactor);
}
И в моей основной форме у меня есть следующее в виде кнопки:
QRect portRect = ui->graphicsView->viewport()->rect();
double scaleFactorX;
if(portRect.width() <= (item->boundingRect().size().width()))
scaleFactorX =portRect.width() /(item->boundingRect().size().width());
else
scaleFactorX = (item->boundingRect().size().width())/portRect.width();
qDebug("Scalefactor: %4.3f n", scaleFactorX);
qDebug("item width: %4.3f n", item->boundingRect().size().width());
qDebug("item height: %4.3f n", item->boundingRect().size().height());
item->setScaleFactor(scaleFactorX);
item->scale(scaleFactorX,scaleFactorX);
Где item
находится один из этих ImagePixmapItem
элементов.
В первый раз это работает хорошо — мое изображение больше, чем окно просмотра, и оно хорошо масштабируется, чтобы соответствовать размеру окна (по крайней мере, по ширине). Однако, если я снова нажму на кнопку, вернутся те же значения для scaleFactorX
и item
ширины и высоты.
Можете ли вы изменить boundingRect
изображение после его преобразования? Если нет, что мне следует делать?
Ответ №1:
Прежде всего, QGraphicsItem::boundingRect()
возвращает копию прямоугольника. Его изменение не влияет на фактический элемент. Чтобы изменить геометрию элемента, вам нужно переопределить эту функцию и вернуть другой прямоугольник. И вызывайте prepareGeometryChange()
, когда вы действительно измените его.
Теперь, если все, что вы хотите, это поместить элемент в окно просмотра QGraphicsView, используйте QGraphicsView::fitInView()
.
Изменение преобразования элемента сильно отличается от изменения преобразования сцены в представление. Первый изменяет способ размещения элемента в сцене по отношению к другим элементам. Более поздний вариант сохраняет связь и влияет только на то, как сцена «отражается» на представлении.
Это не имеет большого значения, если у вас есть один элемент в сцене. Просто имейте в виду, когда вы работаете с более сложной сценой, что преобразование элемента связано с математической моделью вашего мира, а не с тем, как ее просматривать.
Редактировать:
Я только что перечитал ваш код. Оказывается, вы неправильно вычисляете масштабный коэффициент. Вот базовый, непроверенный код:
QRect itemSize = graphicsView->mapFromScene(item->sceneBoundingRect()).boundingRect().size();
QRect scaledSize =itemSize.scale(graphicsView->viewport().size(), Qt::KeepAspectRatio);
double ratio = qMin((double)scaledSize.width()/itemSize().width(), (double)scaledSize.height()/itemSize().height());
item->setTransform(QTransform::fromScale(ratio,ratio), true);
Смысл в том, чтобы использовать sceneBoundingRect
вместо boundingRect
поскольку boundingRect
это локальные границы элемента, которые всегда одинаковы независимо от преобразования элемента. А sceneBoundingRect — это границы после того, как все transformations
будут применены.
Комментарии:
1. если я использую fitInView, действительно ли это масштабирует сам ЭЛЕМЕНТ? Имейте в виду, если у меня есть несколько элементов в сцене, я на самом деле хочу манипулировать единственным элементом, который имеет фокус, чтобы он помещался в представление, а не просто увеличивать, чтобы само представление масштабировалось, чтобы соответствовать элементу в представлении
2. Я не понимал, что вы хотите изменять размер отдельного элемента. Тогда
fitToView
это не ответ. Извините. Однако вашsetScaleFactor()
не имеет никакого эффекта вообще, поскольку он просто устанавливает temp. Смотрите мою правку для масштабирования отдельного элемента.