Multiple QGraphicsView for a single QGraphicsScene
Asked Answered
S

2

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);
Sorus answered 9/5, 2013 at 4:21 Comment(0)
T
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;
}
Tabby answered 16/5, 2013 at 11:58 Comment(7)
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 ?Enterprising
@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. doc.qt.io/qt-5/qgraphicsview.html#viewportUpdateMode-propTabby
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.Enterprising
@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: doc.qt.io/qt-5/qwidget.html#repaintTabby
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 )Enterprising
@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()));Tabby
this answer is usefulArboretum
I
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
Inflect answered 14/5, 2013 at 9:8 Comment(4)
I have tried the above mentioned code . Its not resolving the issue. Views are not displaying anything.Sorus
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 ?Inflect
one of reason it was not working was, there was no active painter, it needs to be done under paintEvent()Inflect
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?Sorus

© 2022 - 2024 — McMap. All rights reserved.