1
votes

I am trying to move around the viewport displayed by the GraphicsView. According to Qt documentation, this is can be done by calling the translate() method of the QGraphicsView class.

I have tried to do this without success so far and I haven't found an explanation to this problem so far. Can anyone help me ? I created a simple example that shows my problem :

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QGraphicsScene *scene = new QGraphicsScene();
    ui->graphicsView->setScene(scene);
    ui->graphicsView->scene()->addItem(new QGraphicsLineItem(0,-10, 0,10));
    ui->graphicsView->scene()->addItem(new QGraphicsLineItem(-10,0, 10,0));
}

MainWindow::~MainWindow()
{
    delete ui;
}

graphicsView is of a subclassed type of QGraphicsView. Here is its code :

MyGraphicsView::MyGraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
}

void MyGraphicsView::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Up)
        translate(0, 10);
    else if (event->key() == Qt::Key_Down)
        translate(0, -10);
    else if (event->key() == Qt::Key_Left)
        translate(-10, 0);
    else if (event->key() == Qt::Key_Right)
        translate(10, 0);

    update();
}

As the class is very small, I don't think there is a need for sharing the headers. However, if you feel I should do so, just post a comment and I will share them.

1

1 Answers

1
votes

From the QGraphicsView doc:

QGraphicsView keeps the center of the view fixed during a transformation. Because of the scene alignment (setAligment()), translating the view will have no visual impact.

If your purpose is to go over the whole scene, you actually don't have to implement keyPressEvent at all, as QAbstractScrollArea (which QGraphicsView inherits) has done that for you. The only thing you need to ensure is that the scene is larger than your viewport, so try initializing

QGraphicsScene *scene = new QGraphicsScene(0,0,1500,1500);
ui->graphicsView->setScene(scene);
ui->graphicsView->scene()->addItem(new QGraphicsLineItem(750,730, 750,770));
ui->graphicsView->scene()->addItem(new QGraphicsLineItem(730,750, 770,750));

If your purpose is to move the crosshair composed of the two QGraphicsLineItems across the scene, then a way to do it is:

void MyGraphicsView::keyPressEvent(QKeyEvent *event)
{
  int i;
  if (event->key() == Qt::Key_Up){
    for (i = 0; i < items().count(); i++)
        items().takeAt(i)->moveBy(0,-10);//-10, origin is top left
  }
  else if (event->key() == Qt::Key_Down){
    for (i = 0; i < items().count(); i++)
        items().takeAt(i)->moveBy(0,10);
  }
  else if (event->key() == Qt::Key_Left){
    for (i = 0; i < items().count(); i++)
        items().takeAt(i)->moveBy(-10,0);
  }
  else if (event->key() == Qt::Key_Right){
    for (i = 0; i < items().count(); i++)
        items().takeAt(i)->moveBy(10,0);
  }

  update();
}

This iterates through all items (use an actual iterator if you like) and moves them all according to your wishes. It's not a very elegant solution, but I believe it's not what you're after.