Reputation: 544
I am trying to make a QGraphicsView
with same width as height positioned in center of the window.
I created a ordinary QGraphicsView
in Qt Designer and set minimal size, added some calculations that center the QGraphicsView
into center of the main window and that set the same width as height. It uses only setGeometry
. Than I created a QGraphicsScene
with only one very long rectangle. I want the graphics scene to fit to view so I have used QGraphicsView::fitInView
. Everything works OK, but the problem cames with resizing window.
When I increase height and width of the window everything also works fine. The QGraphicsView
has a new position and a new size. When I reduce only a part of size of the window everything still works fine. But (finally) when I reduce the size of window to the possible minimum everything breaks. The rectangle in view has the right width (the same as without resizing, I have measured it with a ruler :) ), but a new margin is created and also QGraphicsView
is not positioned and sized right (so it is not only the margin, but maybe also the setGeometry
has no effect).
I have noticed, that the same thing happens when I call QGraphicsView::fitInView
before using setGeometry
.
It is getting me crazy, please help!
Here is some code:
void MainWindow::resizeEvent(QResizeEvent *e)
{
int h = e->size().height(),
w = e->size().width(),
s;
if(w > h) s = h-120;
else s = w-120;
ui->board->setGeometry((w-s)/2,(h-s)/2,s,s);
int scaleWidth = ui->board->scene()->width(),
scaleHeight = ui->board->scene()->height();
ui->board->fitInView(QRectF(0, 0, scaleWidth, scaleHeight), Qt::KeepAspectRatio);
}
Here are images of what happens to QGraphicsView
, the rectangle is red, view is blue:
Upvotes: 3
Views: 23362
Reputation: 5289
I needed to do the same thing but in a DialogForm...
I defined the Class header like this
#ifndef MAP_H
#define MAP_H
#include <QDebug>
#include <QDialog>
#include <QImage>
#include <QGraphicsPixmapItem>
namespace Ui {
class Map;
}
class Map : public QDialog
{
Q_OBJECT
public:
explicit Map(QWidget *parent = nullptr);
~Map();
private:
Ui::Map *ui;
QPixmap *m; // This will load the Original Image
QGraphicsScene* scene; // This is the object passed to the Graphics Viewer
QPixmap *scaledImage; // This is the Scaled Image. It is created each resize from the Original Image (m)
void resizeEvent(QResizeEvent *);
};
#endif // MAP_H
The Dialog Form is very simple and looks like this, it is a GraphicsView with OK/Cancel button.
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Map</class>
<widget class="QDialog" name="Map">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>675</width>
<height>486</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGraphicsView" name="graphicsView"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Map</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Map</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
The Implementation of the class is like this....
#include "map.h"
#include "ui_map.h"
Map::Map(QWidget *parent) :
QDialog(parent),
ui(new Ui::Map)
{
ui->setupUi(this);
scene = new QGraphicsScene();
QWidget::setMouseTracking(true);
m = new QPixmap ("/usr/local/share/pixmaps/gpredict/maps/nasa-topo_1600.jpg");
}
Map::~Map()
{
delete m;
delete scene;
delete ui;
}
void Map::resizeEvent(QResizeEvent *)
{
qInfo() << "Resize event occurred";
QSize gvs = ui->graphicsView->size();
QSize mvs = m->size(); // Just for interest
qInfo() << "About to scale";
qInfo() << "mvs is " << mvs;
qInfo() << "gvs is " << gvs;
QPixmap scaled_img = m->scaled(gvs, Qt::IgnoreAspectRatio);
scene = new QGraphicsScene(this);
scene->addPixmap(scaled_img);
ui->graphicsView->setScene(scene);
}
The Image is now resized whenever the dialogForm is resized. It is (importantly) resampled from the original image, else there could be a loss of image quality.
I am only on day 2 of QT programming - trying to get my head around how it is wired up, but I hope this helps someone.
Upvotes: 0
Reputation: 684
I was trying to use QGraphicsView::fitInView
with Qt::KeepAspectRatio,
and was running into similar issues.
I found this answer helpful:
How to anchor QGraphicsView to a special point on a scene?
It seems the key is to manually set the scene's bounding rectangle. The following code worked for me:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Set up graphics view
scene = new QGraphicsScene(this);
drawMyWidget();
scene->setSceneRect(-1.25, -1.25, 2.5, 2.5); // your scene's bounding rect here...
ui->graphicsView->setScene(scene);
ui->graphicsView->show();
}
void MainWindow::resizeEvent(QResizeEvent *) {
QRectF bounds = scene->itemsBoundingRect();
bounds.setWidth(bounds.width()*0.9); // to tighten-up margins
bounds.setHeight(bounds.height()*0.9); // same as above
ui->graphicsView->fitInView(bounds, Qt::KeepAspectRatio);
ui->graphicsView->centerOn(0, 0);
}
Upvotes: 10