Search code examples
c++qtqgraphicsviewqgraphicsscene

How do you change a QGraphicsScene from another function?


My program has a QGraphicsView called SimulatorGV and it has a QGraphicsScene called Simulation. In the main function I have drawn a few rectangles and ellipses. I want to be able to draw on the same scene in another function too.

In essence, how do you add shapes to a scene from another function? (Which is called when a button on the user interface is pressed)


So far I've tried to pass the QGraphicsView to the other function? Below is the main ui function (irrelevant statements cut out):

{
    ui->setupUi(this);
    Simulation = new QGraphicsScene(this);


        ui->SimulatorGV->setScene(Simulation);

        Simulation->addRect(0,415,20,50,noPen,greyBrush); 
        Simulation->addRect(425,230,10,420,noPen,goldBrush); 
        Simulation->addEllipse(80,90,700,700,greyPen,noBrush); 
        Simulation->addRect(72,215,90,450,noPen,blackBrush); 

}

In the header file I declared this function in the private slots:

void DrawingSimulation(QGraphicsView *SimulationGV);

Should it be like this instead?

void DrawingSimulation(QGraphicsScene *Simulation);

I called the function in another function like this:

DrawingSimulation(ui->SimulatorGV);

Should it be like this instead?

DrawingSimulation(ui->SimulatorGV->Simulation);

or?

DrawingSimulation(ui->Simulation);

This is the function I want to be able to draw on the scene from:

void RASP::DrawingSimulation(QGraphicsView *SimulationGV)
{
    for (int i = 0; i < DisplayAlphaParticleNumber; i++)
    {
        if (ParticleLocation[i*6+3] != 0 || ParticleLocation[i*6+6] != 0) 
        {
            ui->SimulatorGV->setScene(Simulation);
            Simulation->addEllipse(ParticleLocation[i*6+3],ParticleLocation[i*6+4],10,10);
        }
    }
}

SimulatorGV is the name of the QGraphicsView in my ui form. RASP is the name of the project. ParticleLocation[i*6+3] is the x coordinate and [i*6+4] is the y coordinate.

Was I right to pass the QGraphicsView onto the varibale instead of the QGraphicsScene Simulation?

Did I pass it correctly?

In the DrawingSimulation function did I add the ellipse correctly?

Edit: In essence, how do you add shapes to a scene from another function? (Which is called when a button on the user interface is pressed)

When a button is pressed this function is called:

    void RASP::on_Button1_clicked()
    {
    //some values set
    //some other functions called then the main one that leads to the drawingsimulation   

     mainfunction();
    }

Then inside the mainfunction():

void RASP::mainfunction()
{
     DrawingSimulation(); //is called
}

Now the function DrawingSimulation() which I would like to draw on the original scene in the RASP::RASP() (MyClass::MyClass) is called.


My previous attempt was to have a boolean function that is set true by the button then the addEllipse:

MyClass::MyClass()
{
ui->setupUi(this);
        Simulation = new QGraphicsScene(this);


            ui->SimulatorGV->setScene(Simulation);

            Simulation->addRect(0,415,20,50,noPen,greyBrush); 
            Simulation->addRect(425,230,10,420,noPen,goldBrush); 
            Simulation->addEllipse(80,90,700,700,greyPen,noBrush); 
            Simulation->addRect(72,215,90,450,noPen,blackBrush); 

if (SimulationRun == true)
{
for (int i = 0; i < DisplayAlphaParticleNumber; i++)
        {
            if (ParticleLocation[i*6+3] != 0 || ParticleLocation[i*6+6] != 0) 
            {
                ui->SimulatorGV->setScene(Simulation);
                Simulation->addEllipse(ParticleLocation[i*6+3],ParticleLocation[i*6+4],10,10);
            }
        }
}
}

and then in the button clicked function setting SimulationRun = to true.


Solution

  • Let's keep it simple.

    If you have:

    MyClass::MyClass() : ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        Simulation = new QGraphicsScene(this);
    
        ui->SimulatorGV->setScene(Simulation);
    
        Simulation->addRect(0,415,20,50,noPen,greyBrush); 
        Simulation->addRect(425,230,10,420,noPen,goldBrush); 
        Simulation->addEllipse(80,90,700,700,greyPen,noBrush); 
        Simulation->addRect(72,215,90,450,noPen,blackBrush); 
    }
    

    If this works, then, this will work too:

    MyClass::MyClass() : ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        Simulation = new QGraphicsScene(this); // supposing MyClass has a Simulation attribute of type QGraphicsScene
    
        ui->SimulatorGV->setScene(Simulation);
    
        addItems(); // calling function below
    }
    
    void MyClass::addItems()
    {
        // declared "void addItems();" in header file
        addItems( Simulation ); // calling function below that could be static
    }
    
    void MyClass::addItems( QGraphicsScene* simu )
    {
        // declared "static void addItems(QGraphicsScene* simu);" in header file
        simu->addRect(0,415,20,50,noPen,greyBrush); 
        simu->addRect(425,230,10,420,noPen,goldBrush); 
        simu->addEllipse(80,90,700,700,greyPen,noBrush); 
        simu->addRect(72,215,90,450,noPen,blackBrush); 
    }
    

    Then, if this works, you now know how to modify the secene from "another function".

    Finally, you should also have:

    void MyClass::DrawingSimulation()
    {
        // declared "void DrawingSimulation();" in header file
        DrawingSimulation( Simulation );
    }
    
    void MyClass::DrawingSimulation(QGraphicsScene *simu)
    {
        // declared "void DrawingSimulation(QGraphicsScene *simu);" in header file
        for (int i = 0; i < DisplayAlphaParticleNumber; i++)
        {
            if (ParticleLocation[i*6+3] != 0 || ParticleLocation[i*6+6] != 0) 
            {
                simu->addEllipse(ParticleLocation[i*6+3],ParticleLocation[i*6+4],10,10);
            }
        }
    }
    

    Note that DrawingSimulation() could also be a slot (declare it using public slots: in your header file. Then, if you connect it to the clicked() signal of a QPushButton of your GUI (for instance), it will be called when the button is clicked and ellipse will be added.

    Like this:

    MyClass::MyClass()
    {
        ...
    
        connect( ui->pushButton, SIGNAL(clicked()), this, SLOT(DrawingSimulation()) );
    }