6

I have one QGraphicsScene to which I have added some instances of QGraphicsItem.

I need to display a particular section of my whole scene in individual views.

To do that, I want to create multiple instances of QGraphicsView each of which displays a particular section of my QGraphicsScene(not a similar portion).

How can it be done?

QGraphicsScene mcpGraphicsScene = new QGraphicsScene(this);

QGraphicsRectItem * mcpGraphicsRect = mcpGraphicsScene->addRect(5,5,200,200);

QGraphicsLineItem * mcpGraphicsLine = mcpGraphicsScene->addLine(500,500,300,300);


QGraphicsView * mcpGraphicsView1 = new QGraphicsView(this);
mcpGraphicsView1->setScene(mcpGraphicsScene);
mcpGraphicsView1->setGeometry(260,20,311,500);

QGraphicsView * mcpGraphicsView2 = new QGraphicsView(this);
mcpGraphicsView2->setScene(mcpGraphicsScene);
mcpGraphicsView2->setGeometry(260,520,311,1061);
paisanco
  • 4,098
  • 6
  • 27
  • 33
Abhishek
  • 338
  • 5
  • 20

2 Answers2

6

You are using the wrong function, you are using setGeometry which is telling the View where it should be placed relative to its parent (which is the widget, not the scene). To define the area of the scene that the view is responsible for showing you need to call use setSceneRect

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QLayout>

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

    QHBoxLayout* myLayout = new QHBoxLayout(this);
    QGraphicsScene* mcpGraphicsScene = new QGraphicsScene(this);

    mcpGraphicsScene->addRect(5,5,200,200);
    mcpGraphicsScene->addLine(500,500,300,300);

    QGraphicsView * mcpGraphicsView1 = new QGraphicsView(mcpGraphicsScene, this);
    mcpGraphicsView1->setSceneRect(0,0,150,150);

    QGraphicsView * mcpGraphicsView2 = new QGraphicsView(mcpGraphicsScene, this);
    mcpGraphicsView2->setSceneRect(0,150,600,600);

    myLayout->addWidget(mcpGraphicsView1);
    myLayout->addWidget(mcpGraphicsView2);
    QWidget *window = new QWidget();
    window->setLayout(myLayout);
    setCentralWidget(window);
}

MainWindow::~MainWindow()
{
    delete ui;
}
Phil Hannent
  • 12,047
  • 17
  • 71
  • 118
  • Hi, got a doubt, I have multiple graphicsView() inside graphcsScene(). Each one draws the same thing from a single DrawItem class that inherits QGraphicsItem. Now how to update the individual graphicsView() from the MainWindow ? – jxgn May 25 '15 at 07:07
  • @XavierGeoffrey that is really a different questions. The view's update policy is set by the QGraphicsView::setViewportUpdateMode(), if you setup the update mode to none then you have to manually call update. That could happen via a signal/slot or direct invocation. However the Smart update has always worked out best for me. http://doc.qt.io/qt-5/qgraphicsview.html#viewportUpdateMode-prop – Phil Hannent May 26 '15 at 11:07
  • Hi, thanks for your time. I am already manually calling update on a `QTimer` signal/slot. My problem is, I have 10 identical graphics item in the `Mainwindow` with 10 `QTimer`. In the signal/slot, I call just the update(), which triggers all the 10 `paintEvent()`. I would like to know how to control the update of each graphicsview from the `Mainwindow`. – jxgn May 26 '15 at 13:11
  • @XavierGeoffrey Generally you shouldn't need such manual usage of timers, that might mean you end up painting when there has been not changes. However to get to your original question to manually repaint the view you would: this->view->viewport()->repaint(); but be careful not to create a recursive loop: http://doc.qt.io/qt-5/qwidget.html#repaint – Phil Hannent May 26 '15 at 14:19
  • This is how I am calling now.... `connect(item_1->timer, SIGNAL(timeout()),scene_1, SLOT(ui->gv_1->update()));` but it throws the error that it expects `;` but got token `)` – jxgn May 27 '15 at 06:02
  • @XavierGeoffrey This is really not the place for this. You should open your own question. The slot is incorrect, you cannot call: SLOT(ui->gv_1->update()). It should be: connect(item_1->timer, SIGNAL(timeout()), ui->gv_1, SLOT(update())); – Phil Hannent May 27 '15 at 10:02
  • Oh ok. Thanks for your inputs :) – jxgn May 27 '15 at 11:10
  • this answer is useful – Pang-yao Liu Sep 01 '21 at 08:07
1

QGraphicsScene has render API, which you can use to render certain portion of QGraphicsScene. You can render it over QWidget.

void QGraphicsScene::render(QPainter * painter, const QRectF & target = QRectF(), const QRectF & source = QRectF(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio)

something like following, I tested following code works fine.

#include "mygraphicsview.h"

#include <QGraphicsScene>
#include <QPixmap>
#include <QGraphicsView>
#include <QPen>
#include <QBrush>

MyGraphicsView::MyGraphicsView(QWidget *parent) :
    QWidget(parent)
{
    setGeometry(QRect(100,100,300,300));

    scene = new QGraphicsScene(QRect(0,0,600,600));
    scene->addRect(20,20,100,100,QPen(),QBrush(Qt::black));
    scene->addRect(10,150,100,100,QPen(),QBrush(Qt::red));
}

void MyGraphicsView::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    scene->render(&painter,QRect(0,0,300,300),QRect(10,10,200,200));
}


#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H

#include <QWidget>

class QGraphicsScene;

class MyGraphicsView : public QWidget
{
    Q_OBJECT
public:
    MyGraphicsView(QWidget *parent = 0);

    void paintEvent(QPaintEvent *event);
    
signals:
    
public slots:

private:
    QGraphicsScene* scene;
    
};

#endif // MYGRAPHICSVIEW_H
Smar
  • 8,109
  • 3
  • 36
  • 48
Kunal
  • 3,475
  • 21
  • 14
  • I have tried the above mentioned code . Its not resolving the issue. Views are not displaying anything. – Abhishek May 14 '13 at 11:16
  • yes, I realized that it does not work with QGraphicsView, not sure why. But it works fine with QWidget. In your case you don't need QGraphicsView right ? – Kunal May 15 '13 at 01:51
  • one of reason it was not working was, there was no active painter, it needs to be done under paintEvent() – Kunal May 15 '13 at 01:55
  • I need QGraphicsView to visualize the objects in scene as my application is based on GVF . Won't rendering in this manner will create some processing overhead in the application? – Abhishek May 21 '13 at 17:23