QGraphicsView. Translate does not appear to work.



  • Hi all,

    I wrote a simple application to see how Transformations of view work. The translation does not appear to work. The image is displayed in the window as if there was no translation.

    Can you please help me see what I am missing? Thanks in advance.

    @
    #include <QtGui>

    int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QGraphicsScene scene;
    scene.setSceneRect(0,0,500,500);
    
    QImage img("3.png");
    scene.addPixmap(QPixmap::fromImage(img));
    scene.addRect(0,0,500,500);
    
    QGraphicsView view(&scene);
    
    QTransform transform;
    transform.translate(100, 100);
    view.setTransform(transform);
    
    view.show();
    

    return a.exec();
    }
    @



  • The translation will affect where the origin is in the graphics view but it won't shift existing items around (at least not visually).

    I modified your program. This should put the two images at a different location based on the change in the translation. I added the .setPos() to make sure they are both put at the same position.

    @
    #include <QtGui>

    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
       
        QGraphicsScene scene;
        scene.setSceneRect(0,0,500,500);
    
       QGraphicsView view(&scene);
    
       QGraphicsPixmapItem *pix_item;
    
        QImage img("3.png");
        pix_item = scene.addPixmap(QPixmap::fromImage(img));
        pix_item->setPos(0,0);
    

    ...
    QTransform transform;
    transform.translate(100, 100);
    view.setTransform(transform);
    ...
    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(0,0);

        view.show();
     
    return a.exec&#40;&#41;;
    }
    

    @



  • I tried your modifications. Both Images are set at origin (0,0) and only one image is visible as they are overlapping.

    I see 2 images only when I set a different position to the QGraphicsPixmapItem object.

    @
    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(0,0);

    QTransform transform;
    transform.translate(100, 100);
    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(200,200)
    @



  • Sorry, my bad. I should have tried it first.

    This should work:

    @
    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

     QTransform transform;
     transform.translate(100, 100);
     view.setTransform(transform);
       
     pix_item = scene.addPixmap(QPixmap::fromImage(img));
     pix_item->setPos(view.mapToScene(0,0))
    

    @



  • Thanks! I see two images now.

    But my image 3.png has dimensions 150x150, so I was expecting the images to overlap as we translated to (100,100), but they do not.

    Also, if I set the sceneRect of my scene( line 7 in the code below), I am back to square one, my application only displays 1 image. I also reviewed "Qt coordinate systems":http://qt-project.org/doc/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system to figure this out but I am stumped.

    This is my full code:
    @
    #include <QtGui>

    int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QGraphicsScene scene;
    scene.setSceneRect(QRectF(QPointF(0,0),QPointF(500,500)));

    QGraphicsView view(&scene);
    QGraphicsPixmapItem * pix_item;

    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    QTransform transform;
    transform.translate(100, 100);

    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    view.show();

    return a.exec();
    }
    @



  • The function .setSceneRect() sets the bounding rectangle for the scene. If you don't set this the return function is the bounding rectangle of all the QGraphicsItems but if you do set it the return function is what you have set it to. This line shouldn't do anything to the viewport itself.

    It is possible that when you set the sceneRect() you might limit where the viewport can scroll too? Without the line added compare your range of the horizontal and vertical scroll bars to what you see with it added. Maybe the second pixmap is off screen and you can't see or get to it?

    The area of the graphics scene rectangle is based on the area of the viewport (QGraphicsView) and the scale factor. For example, if the viewport is 500x500 and the scale factor is 0.5 for x and y then the graphics scene should have an equivalent size of 1000x1000.

    The QPixmap items should scale when the scale factor is set. You don't have this in your code so the size will always be the same.

    The translation might need to be converted to viewport coordinates to get the proper relative position of the images.

    @
    transform.translate(view.mapToScene(100,100));
    @



  • I can expand the application window. I do not see the second pixmap.

    The image does not scale when I expand or contract the window, there is no scale factor.

    Both the following lines give the same result
    @
    transform.translate(view.mapToScene(100,100).rx(),view.mapToScene(100,100).ry());

    transform.translate(100, 100);
    @

    Yes, from what I understand, sceneRect holds the bounding rectangle of the scene. But I am unable to see how adding the line (line 7 my previous post) is giving us different results as we are working with View coordinate system here



  • I don't see how this causes a problem.

    One thing I did notice (maybe related) is that the function is called on the scene before it is assigned to a view. Maybe moving the line following creating of the QGraphicsView view(&scene) might be the solution. It is possible that some information is required from the view to complete this properly.

    What are you trying to accomplish with setSceneRect() ? The scene rect is calculated automatically to contain all the items you added.



  • I am setting the scene size so I can add more items in the Scene coordinate system and I can make sure each item is going where it should, unlike when sceneRect is resizing.

    I just tried varying the translate coordinates in my code. Some of the values I tried are below.
    @
    transform.translate(200,200);
    transform.translate(1000,1000);
    transform.translate(100,500);
    @

    code:
    @
    #include <QtGui>

    int main(int argc, char *argv[]) {

    QApplication a(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&scene);
    QGraphicsPixmapItem * pix_item;

    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    QTransform transform;
    transform.translate(200,200);
    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    view.show();

    return a.exec();
    }
    @

    This application has just 2 pixmap items. But my final application has more items and transformations. I am trying to make sure the transformations are working in the simple case.

    Thanks



  • I think I can explain both problems (relative position of pixmaps not where they should be and problem with setSceneRect() ).

    The QGraphicsView is dynamically changing when you add items or change the scene bounding rectangle. You set the translation but this is basically lost or altered in favour of trying to center the QGraphicsScene. When I tried using the mapToScene() and mapFromScene() functions with test data I was not getting expected results (should get the same value I started with).

    The key is the transformation anchor. The default is to center the QGraphicsScene which won't work if you are using 'translate'.

    I tried this and it worked:

    @
    #include <QtGui>

    int main(int argc, char *argv[]) {
     
    QApplication a(argc, argv);
       
    QGraphicsScene scene;
    QGraphicsView view(&scene);
    QGraphicsPixmapItem * pix_item;
    
    view.setTransformationAnchor(QGraphicsView::NoAnchor);
       
    QImage img("3.png");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));
     
    QTransform transform;
    transform.translate(200,200);
    view.setTransform(transform);
       
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));
       
    view.show();
       
    return a.exec&#40;&#41;;
    }
    

    @



  • I still have the two problems. The positions of pixmap are not affected by translate (line 19). My image is of dimensions 100x100. So I would expect the second image to be opposite each other with their corners touching. But that does not happen. "Output":http://s6.postimg.org/ze2usrhmp/Screen_Shot_2015_03_03_at_2_37_04_PM.png

    Code:
    @
    #include <QtGui>

    int main(int argc, char *argv[]) {

    QApplication a(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&scene);

    QGraphicsPixmapItem * pix_item;

    view.setTransformationAnchor(QGraphicsView::NoAnchor);

    QImage img("pic100x100.gif");
    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    QTransform transform;
    transform.translate(100,100);

    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    view.show();

    return a.exec();
    }
    @



  • It does work but there is something odd going on.

    The problem is that each time you add an item the internal transformation is changed if the bounding rectangle containing all the items change. That I am sure of. In my example below I increased the size so that anything added would stay within the predefined area and it works fine.

    There must be an option or some other way to lock or prevent the internal matricies from updating when the bounding rect of the items change. I thought the QGraphicsView::Anchor was the answer but it only worked on the program I tested yesterday (I happen to hit on the right combination of features I guess; it was one of the sample Qt programs I was using).

    Anyway, here is my test code and screen shot. The image size is 64x64 pixels.

    https://www.dropbox.com/s/mj3di51k4ypfia2/test.png?dl=0

    @
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);
    QTransform transform;
    QGraphicsPixmapItem * pix_item;

    view.setTransformationAnchor(QGraphicsView::NoAnchor);

    // bounding rect won't change size, doesn't need to.
    scene.setSceneRect(-1000,-1000,1000,1000);

    QImage img("/Users/ron/64x64.png");

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    transform.translate(64,64);
    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    transform.translate(64,-64);
    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    transform.translate(64,64);
    view.setTransform(transform);

    pix_item = scene.addPixmap(QPixmap::fromImage(img));
    pix_item->setPos(view.mapToScene(0,0));

    view.show();

    return a.exec();
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.