[SOLVED] How do I simply update scene after adding a new element?



  • I'm writing a simple desktop application to simulate the RRT algorithm.
    So, I set up a simple window with a graphicsView from the ui editor. In the window constructor, I added a scene, like this:
    [code]
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    scene->setSceneRect(0, 0, vWidth, vHeight);
    [/code]
    where vWidth and vHeight have been previously set. I then start adding graph's points and edges. I have a "START" button that starts adding points and edges, but the scene updates only when the whole graph has been computed (this is done in a while loop). To avoid these, since I'd like to see the graph construction "step-by-step", I added
    [code]
    ui->graphicsView->viewport()->repaint();
    [/code]
    after every point/edge insertion on the scene, done via
    [code]
    scene->addEllipse(...)
    scene->addLine(...)
    [/code]
    This, on the other hand, freezes the ui until the whole graph has been drawn, so I can't stop or pause the process, or even simply close the window.

    So, how could I do this? Shall I use threads? Any example? Thanks.



  • @alogim

    Stopping is not difficult.
    For example:

    If you call QCoreApplication::processEvents ()

    after each line you want to be able to stop, for example:
    scene->addEllipse(...)

    user will be able to interact with gui.
    This should also let the view update. I do not think you need ui->graphicsView->viewport()->repaint();

    As soon you are able to interact with GUI, clicking on your stop button should set the flag to stop.

    For example:

    • for simplicity assume you need to call only one function scene->addEllipse(...) in a loop, until stop button is not pressed or you are done;
    • bool toStop is a flag to stop processing.
    • **addItemsTo **scene is function which adds all items to the scene:
    • onStopClicked() is a slot which is called on stop button click
    • myWindow is the widget owner of ui.

    void myWindow::onStopClicked()
    {
    toStop = true;
    }

    void myWindow::addItemsTo()
    {
    const int itemsToAdd = 10;
    toStop = false;
    for ( int i=0; i< itemsToAdd ; i++ )
    {
    QCoreApplication::processEvents () ;
    if( toStop ) // user requested to stop
    break;

        scene->addEllipse(...)
    

    }

    }

    You might also want to disable all the controls you do not want user be able to interact with at the beginning of the addItemsTo and restore their state at the end.

    Pausing would be more complicating since you need to know how to continue.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You could also just use a QTimer that would call periodically as slot where you add your points/ellipses etc.
    The stop button would just have to cancel the QTimer.

    Hope it helps



  • @alex_malyu
    Thank you very much alex. I just tried what you suggested and it works perfectly.

    @SGaist
    I thought about slots and timer too, as suggested in the examples on qt's site, but it requires subclassing a QGraphicsItem for each item in the QGraphicsView. The problem is, I don't know the number of items that will be generated until runtime, and apart from this, creating 10.000 classes (one for each item) would be very resource intensive, I think.
    Anyway, the method above, the one with
    QCoreApplication::processEvents () ;
    works perfectly for my purpose.
    So thanks both for your politeness: it is very nice to see such a great community :)


Log in to reply
 

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