[SOLVED]Qt 5.2.1 GraphicsView::drawBackground and drawForeground are not called after GraphicsView::Update()



  • Hi.

    We are porting application from Qt4.8.x to Qt5.x. So far the task has been easy. Now we have one problem.

    In Q4.8, inside subclassed QGraphicsView::mouseMoveEvent we call "this->update();" that results call of GraphicsView::paint and QGraphicsView::drawBackground and ..drawForeground.

    This is not happening in Qt5.2.1. How QGraphicsView::drawBackground (paint event) can be generated in Qt5.x?

    ..drawBackground is called if we use CenterOn-function for example.

    Kind regards,
    Erkki
    Tampere, Finland


  • Moderators

    One way is to invalidate the scene rectangle:
    @
    scene()->invalidate(scene()->sceneRect());
    @



  • Some unknown reason it ( scene()->invalidate(scene()->sceneRect()); ) does not generate paint event to QGraphicsview (logged both mouse and paint event).

    The update mode is QGraphicsView::BoundingRectViewportUpdate.

    I can generate paint-events by calling function centerOn. Problem of that solution is that picture drifts a little on every mousemove event.


  • Moderators

    Can you show your code? I tried this and it works just fine:
    @
    class GV : public QGraphicsView {
    public:
    GV(QWidget* parent = nullptr) : QGraphicsView(parent) {
    setMouseTracking(true);
    }
    void paintEvent(QPaintEvent* evt) {
    qDebug() << "paintEvent";
    QGraphicsView::paintEvent(evt);
    }
    void drawBackground(QPainter* p, const QRectF& r) {
    qDebug() << "drawBackground";
    QGraphicsView::drawBackground(p,r);
    }
    void mouseMoveEvent(QMouseEvent* evt) {
    qDebug() << "mouseMoveEvent";
    QGraphicsView::mouseMoveEvent(evt);
    scene()->invalidate(scene()->sceneRect());
    }
    };

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    auto gv = new GV(this);
    gv->setScene(new QGraphicsScene(this));
    setCentralWidget(gv);
    }
    @
    Output when I hover mouse over graphics view is:
    @
    mouseMoveEvent
    paintEvent
    drawBackground
    mouseMoveEvent
    paintEvent
    drawBackground
    mouseMoveEvent
    paintEvent
    drawBackground
    ...
    @



  • First, thanks for bullet proof example!

    I checked your example it looks that I am doing things similar way.

    Here is the code (I can mail whole file if needed):

    Initialization of instance:
    @

    #if 0
    setRenderHints(DEFAULT_RENDER_HINTS);
    /* optimization mode */
    setOptimizationFlags (
    QGraphicsView::DontAdjustForAntialiasing);
    #else
    setRenderHints( QPainter::TextAntialiasing);
    #endif
    setCacheMode(QGraphicsView::CacheNone);

    setCursor(Qt::ArrowCursor);
    setInteractive (true);
    setMouseTracking(true);
    
    
    setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    
    setAlignment(DATA_ALIGNMENT); // align data to bottom.
    

    @

    Paint:

    @

    void timelinegraphicsdataview::paintEvent ( QPaintEvent * event )
    {
    #ifdef TIMELINEGRAPHICSVIEWPERFORMANCEDEBUG
    FUNCTIONSCOPE;
    #endif

    LOGFREETEXT("paintEvent");
    
    
    if (event==NULL) return;  // do not handle null event
    
    if( ( IsViewOn() == true && mCanPaint == true )
       || mInfoText.length()> 0 )
    {
        QElapsedTimer mgfx_render_timer;
    
        mgfx_render_timer.start();
        
        if (mFirstPaintAfterLoad==true)
        {
            /* Update channel height information */
            /* Do here adjustments needed after 1st load */
            mFirstPaintAfterLoad = false;
        }
    
        /* Paint */
        QGraphicsView::paintEvent ( event );
    
        // Statusbar text
        QString a;
        mperf_gfx_render_time_ms = mgfx_render_timer.elapsed();
    

    #ifdef TIMELINEGRAPHICSVIEWPERFORMANCEDEBUGSTATS
    LOGVALUE("Screen Paint Time",mperf_gfx_render_time_ms)
    #endif
    if (mperf_gfx_render_time_ms>0)
    {

    #ifdef TIMELINEGRAPHICSVIEWPERFORMANCEDEBUGSTATS
    StringInt renderGroup("timelinegraphicsdataview Render");
    DebugAPI::Instance()->StoreDebugValue(renderGroup, "time", QString("%1ms").arg(mperf_gfx_render_time_ms));
    #endif
    }
    }
    }

    @

    MouseMove:

    @

    void timelinegraphicsdataview::mouseMoveEvent(QMouseEvent* event)
    {
    FUNCTIONSCOPE;
    /* Enable UI once data is available on screen */
    if (mJamUI == false && event!=NULL && mCanPaint == true)
    {
    if(IsViewOn() == true)
    {

            LOGFREETEXT("Scene update");            
            scene()->invalidate(scene()->sceneRect());
    
          ... <snipped something since posting has size limit >
    

    ementSec,mChannelToBeOffsetAdjusted);

                /* This is needed for updating value abs graphs */
                RefreshAllviews_slot();
            }
    
            /* trigger one update that causes background draw
           and hence crosshair update */
           this->update();
        }       
    }
    if (event!=NULL)
    {
        QGraphicsView::mouseMoveEvent(event); //forward event)
    }
    

    }

    @

    When dealing with Qt 4.8.2, line 23 on above snippet generates paint event. I added your recommendation to line 11. When logging, proper mousemove events are generated but paint events not.

    Our application uses QML for layouting widgets to screen. I am wondering if during porting we messed something there and it prevents somehow update() from working like earlier.



  • I have been reading Qt5 material. There are some mention about Qt5 paint update differences. I will check those.



  • We had problems in porting to QML. We did some refactoring and subclassed items from QQuickView, made wrapper, forwarder events from QQuickView instance to wrapped class things started to work.


Log in to reply
 

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