QScroller in QGraphicsView resets viewport origin (Qt 5.7) - qt

I have a simple subclass of QGraphicsView that I'd like to enhance with kinetic scrolling. My QGraphicsScene sceneRect is something like (origin = -12500,12500 w=25000, h=25000), so is centered on 0,0, but extends far negative and far positive. In the QGraphicsView, when I attempt:
if(clicked)
{
// Enable kinetic effects -- should work, but doesn't
QScroller::grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture);
// this behaves as I expect:
// this->setDragMode(QGraphicsView::ScrollHandDrag);
}
When dragging, viewport's image truncates everything < 0,0 in Scene Coordinates, plus when I release the mouse, the viewport jumps so that the Scene 0,0 is located at the View 0,0 (upper left). When in this mode, the scroll bars work as expected. Hopefully, the picture included below will help...
Very confusing.
I've tried attaching the grab gesture to both the QGraphicsView and the QGraphicsView->viewport() and neither work as I expect...
Picture of Before, During, After kinetic drag

Related

fit QGraphicsScene to QGraphicsView

I'm trying to draw a stacked bar graph on Qt, i followed the tutorial on the documentation but when i try to put the graph inside a QGraphicsView i get a lo of unused space and can't manage to make the scene fit the view.
My code is the same as the documentation one plus the following to make the scene show up in the view:
QGraphicsScene *scene = new QGraphicsScene(this);
scene->addWidget(chartView);
ui->view->setScene(scene);
And what i get is this
As you can see there is a lot of unused space and it makes the text disappear, i wanted to make the graph fit the view but i can't seem to find a way to do so.
I tried in many different ways using
ui->view->ensureVisible ( scene->sceneRect() );
ui->view->fitInView( scene->sceneRect(),Qt::KeepAspectRatio);
and
ui->view->setSceneRect(0,0,ui->view->frameSize().width(),ui->view->frameSize().height());
but nothing seems to work (the second solution just moves the graph to the top left)
As per the comment... the real issue is the basic sizing of chartView rather than anything to do with QGraphicsView or QGraphicsScene.
When a QWidget is added to a QGraphicsScene the resulting QGraphicsProxyWidget will generally honour the size hint and policy of that widget.
In addition, though, the QGraphicsScene will set the scene rect to the bounding rectangle of all scene items and the QGraphicsView will then position the scene according to whatever viewport anchor is in force. The end result can be visually misleading if the scene has a complex set of items or has a bounding rectangle smaller than that displayed within the GraphicsView.
So if a widget does look odd when added to a QGraphicsScene it's normally a good idea to test by just showing it as a top level window on the desktop and make sure it behaves as expected before going any further.

QGLWidget image disappears after resizing window

I am working on some software to display semitransparent images in a row.
It worked fine using glut functions for resizing etc. but then i decided to move to Qt for a GUI.
all glut functions are stripped and i use a QGLWidget to render my OpenGL stuff.
When i open the program, everything works as wanted but as soon as i resize the mainwindow (and thus the QGLWidget is being resized) the contents of my openGL widget disappear or appear cluttered.
Strangely though the widget is completely grey (my glclearcolor) when there is no cluttered render of my scene content.
This is how it should look like (after starting the program):
http://abload.de/img/okw0qh0.png
And this is how it looks like after resizing the mainwindow:
http://abload.de/img/errort1peu.png
(sometimes it is just grey)
my resizeGL function looks like this and gets called properly:
void prosta3dwidget::resizeGL(int width, int height)
{
if (height == 0) return; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height; //get aspect ratio
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.5f, 100.0f);
glViewport(0, 0, width, height);
update(); //redraw content
glMatrixMode(GL_MODELVIEW);
}
Okay, noticing that this must have something to do with the depth buffer (gluPerspective manual notes that depth buffer precision is affected by zNear and zFar values: https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml )
i disabled the GL_DEPTH_TEST (uncommented glEnable(GL_DEPTH_TEST)) and everything seems to work as desired. yet i dont fully understand why.
problem solved, new mistery achieved.

Qt/PySide/PyQt - QGraphicsScene drawing fail when zooming in

I am using QGraphicsScene and View in Qt/PySide and have troubles using scaling the view - zoomin in.
I have a very simple scene:
scene = QtGui.QGraphicsScene()
scene.addText("hello!")
scene.addRect(0, 0, 50, 20)
view = QtGui.QGraphicsView(parent)
view.setScene(scene)
What I see is OK. When I zoom in using view.scale(factor, factor) and look at the lower left corner, it still is OK.
... but when I zoom even closer, it gets broken. Rectangle is no more rectangle and I can see a diagonal line while the bottom line is missing.
What is wrong with my code? Or is it error in Qt library? Does it happen also in Qt with C++.

How to get pixel on QGraphicsPixmapItem on a QGraphicsView from a mouse click

I have a QGraphicsScene with a QGraphicsPixmapItem on it, showing an image. I also have a view showing the scene. I have a mousePressEvent() function defined, looking for mouse clicks on the view.
The view is setup to contain the pixmap:
//pixmap is a QGraphicsPixmapItem *
view->fitInView(pixmap, Qt::KeepAspectRatio);
I can get the position of a mouse click in the view's coordinate system:
//e is my QMouseEvent *
QPoint local_pt = view->mapFromGlobal(e->globalPos());
Now I'd like to map this point to the original image coordinates, using any combination of the QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
I've tried pixmap->boundingRect(), which gives me a QRectF(0,0 778x582), which has the appropriate dimensions (of the original image), but I do not see how the x and y coordinates are related to the local point of the click.
How do I get position of the mouse click in the original image coordinates?
EDIT:
This is what ultimately worked:
//e is my QMouseEvent *
QPoint local_pt = view->mapFromGlobal(e->globalPos());
QPointF img_coord_pt = view->mapToScene(local_pt);
img_coord_pt is (0,0) when I click the top left corner of the image, and (image width, image height) at the bottom right corner.
QGraphicsView::mapToScene maps screen coordinates to scene coordinates, then use QGraphicsView::itemAt to get the item and QGraphicsItem::mapFromScene to map scene global coordinates to item local coordinates.
There are inverses of these, of course.

How to get visible scene rectangle of QGraphicsView?

I'm displaying a map built as rectangle of QGraphicsPixmapitem items (each item stands for one map tile). Because my map is quite large (around 30 MB of PNG files) I want to be able to load pixmaps on demand only when they're visible for user in QGraphicsView and unload when they became invisible.
Is there any way to figure out visible scene rectangle?
This gives you the visible scene rectangle:
sceneRect = graphicsView.mapToScene(graphicsView.rect()).boundingRect()
In case there is a shear or rotation transformation present it gives you the bounding rectangle of the visible scene area. If you do not have such transformations (only shift or zoom) the returned rectangle is the exact scene area.
Now for your real problem of efficiently display a huge tiles map in a scene? You could load the tiles in background and first evaluate if your Qt framework isn't already optimized for big pixmap that are outside the visible range. 30 MB also doesn't sound so big that it wouldn't fit into memory.
QGraphicsView inherits the QWidget::geometry() function. You can use this to determine its location and size within its parent widget. (Outside of its constructor)
The QGrapicsScene can be larger than the QGraphicsView. The default QGraphicsView will add horizontal and vertical scroll bars to house the QGraphicsScene. I imagine you would like to do something like this:
//create a QGraphicsScene (for this example *scene) that is the size of your entire map.
QGraphicsScene *scene=new QGraphicsScene(0,0,mapWidth,mapHeight);
//create a QGraphicsView* named view that is the size of your visible area
//I'm assuming visibleHeight and visibleWidth do not change (this is your viewing window)
QGraphicsView *view=new QGraphicsView(0,0,visibleWidth,visibleHeight);
view->setScene(scene);
Have the user control the x and y position of the scene that triggers some custom signal like sceneMoved(int,int). Before you redraw the scene, call a slot to check the new position of the scene:
connect(this,SIGNAL(sceneMoved(int,int)),this,SLOT(drawScene(int,int)));
void SomeClass::drawScene(int newX, int newY){
//if you already have a pointer to the scene do this, or call
//QGraphicsView::scene();
int oldX=scene->geometry()->x();
int oldY=scene->geometry()->y();
//now that you have your oldX, oldY, newX, and newY, visibleWidth, visibleHeight
//you can determine what you need to redraw, what you need to delete, and what can stay
}
There is still a lot of if..else, but you get the point. I suggest trying to segment your map into squares the size of your visible area.

Resources