[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 -
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.
-
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.
-
use QGraphicsView::resetCachedContent() to redraw background
Resets any cached content. Calling this function will clear QGraphicsView's cache. If the current cache mode is CacheNone, this function does nothing.
This function is called automatically for you when the backgroundBrush or QGraphicsScene::backgroundBrush properties change; you only need to call this function if you have reimplemented QGraphicsScene::drawBackground() or QGraphicsView::drawBackground() to draw a custom background, and need to trigger a full redraw.
See also cacheMode().