Увеличить QGraphicsItem, чтобы он соответствовал QGraphicsView

#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. Смотрите мою правку для масштабирования отдельного элемента.