[Solved] QGraphicsView not updating



  • For solution, see my reply below.

    --

    Hi, I did a quick search in Google and it seems this problem is not unique to me. I'm developing in Windows 7, 64-bit.

    I am busy writing a simple raytracer with multiple threads updating tiles with image data, then posting events back to the main thread whenever a tile is finished (I also post an event just as I'm about to start on a tile). I don't want to allocate/deallocate memory once the threads get started, so for displaying the data I have three QLists:

    @ QList<QImage*> images; // images corresponding to tiles; not actually used yet in example below
    QList<QPixmap*> pixmaps; // pixmaps corresponding to tiles
    QList<QGraphicsPixmapItem*> items; // items for scene added pixmaps@

    The threads will only be modifying floating point arrays (with appropriate mutexes and things); the main thread will, on a custom event, copy the tile data to an already allocated QImage, convert from that to an already allocated (and added to scene) QPixmap and call update() on an earlier stored QGraphicsPixmapItem which was returned when the QPixmap was added to the scene.

    The problem is that the scene doesn't actually update. The QGraphicsView does show the original contents that I added to the scene in the constructor. The scene also does update when I resize the window on which the scene is the central widget. But no matter what I do (calling update() on anything it can be called on), the thing doesn't actually update. Here is the custom event handler that I believe should be causing an update (I also understand this to be running in the main thread):

    @bool MainWindow::event(QEvent *e)
    {
    if (inRange((int)e->type(), (int)QEvent::User, (int)QEvent::User + 1)) // inRange is a bool function that just does a range check
    {
    QRenderTileEvent renderTileEvent = (QRenderTileEvent)e; // Custom event that includes the tile's coordinates (which tile)
    int index = renderTileEvent->I * image.Width + renderTileEvent->J; // Index calculated from tile coordinates to address the correct QImage, QPixmap and QGraphicsPixmapItem in my QLists

        if (index < pixmaps.count())
        {
            if (e->type() == QEvent::User)
                pixmaps[index]->convertFromImage(underConstructionImage); // For now I don't use the thread's render data, just a tile sized image which indicates the thread is working on this tile
            else
                pixmaps[index]->convertFromImage(notUnderConstructionImage); // For now I don't use the thread's render data, just a tile sized image which indicates the thread is finished with this tile
            items[index]->update();
            graphicsView.update();
            graphicsView.viewport()->update(); // I confirmed with a breakpoint, this line does execute repeatedly
    
        }
        return true;
    }
    else
        return false;
    

    }@

    As indicated in the comments, I don't yet use the threads output data, just two preloaded images to indicate which tiles the threads are working on.

    I can send more code (possibly a minimal example) if it is not obvious what I'm doing wrong.



  • In overriding QMainWindow::event() I should have not simply returned false in case of not handling the event myself, I should have had

    @return QMainWindow::event(e);@

    That solved it.


Log in to reply
 

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