c++ - Draw an item in a static location relative to the QGraphicsView -
i draw notification appears in upper right corner of qgraphicsview
. however, qgraphicsitems
positions specified in scene coordinates, if user panned/zoomed view different part of scene, notification move off screen.
i have figured out simulate behavior moving , scaling notification time current view changes. seems terribly ineffective , not @ elegant.
it seems qgraphicsview
should support kind of behavior. docs mention flag itemispanel
sounds hopeful, mentions nothing static placement in view. itemignorestransformations
scaling/zooming, not panning.
is there built-in qt functionality supports behavior?
the naive solution of having notification part of original scene bad - breaks model-view separation. can have multiple views, showing 1 scene, on 1 of them can notification appear desired.
another simple way overlay qwidget notification on top of view. problem on architectures, overlaying regular qwidgets on top of accelerated qglwidgets make former disappear. note qgraphicsview's viewport may qglwidget!
thus, portable solution explicitly painting on top of else in qgraphicssceneview's viewport()
.
below complete example.
// main.cpp #include <qapplication> #include <qgraphicsscene> #include <qgraphicsview> #include <qgraphicsitem> qreal rnd() { return qrand() / (float)rand_max; } class overlaidgraphicsview : public qgraphicsview { q_object qgraphicsscene * m_overlayscene; public: explicit overlaidgraphicsview(qwidget* parent = 0) : qgraphicsview(parent), m_overlayscene(null) {} explicit overlaidgraphicsview(qgraphicsscene * scene = 0, qwidget * parent = 0) : qgraphicsview(scene, parent), m_overlayscene(null) {} void setoverlayscene(qgraphicsscene * scene) { if (scene == m_overlayscene) return; m_overlayscene = scene; connect(scene, signal(changed(qlist<qrectf>)), slot(overlaychanged())); update(); } qgraphicsscene * overlayscene() const { return m_overlayscene; } void paintevent(qpaintevent *ev) { qgraphicsview::paintevent(ev); if (m_overlayscene) paintoverlay(); } virtual void paintoverlay() { qpainter p(viewport()); p.setrenderhints(renderhints()); m_overlayscene->render(&p, viewport()->rect()); } q_slot void overlaychanged() { update(); } }; class window : public qwidget { qgraphicsscene scene, notification; overlaidgraphicsview * view; qgraphicssimpletextitem * item; int timerid; int time; public: window() : view(new overlaidgraphicsview(&scene, this)), timerid(-1), time(0) { (int = 0; < 20; ++ i) { qreal w = rnd()*0.3, h = rnd()*0.3; scene.addellipse(rnd()*(1-w), rnd()*(1-h), w, h, qpen(qt::red), qbrush(qt::lightgray)); } view->fitinview(0, 0, 1, 1); view->setresizeanchor(qgraphicsview::anchorviewcenter); view->setrenderhint(qpainter::antialiasing); view->setoverlayscene(¬ification); item = new qgraphicssimpletextitem(); item->setpen(qpen(qt::blue)); item->setbrush(qt::nobrush); item->setpos(95, 0); notification.additem(item); notification.addrect(0, 0, 100, 0, qt::nopen, qt::nobrush); // strut timerid = starttimer(1000); qtimerevent ev(timerid); timerevent(&ev); } void resizeevent(qresizeevent * ev) { view->resize(size()); view->fitinview(0, 0, 1, 1, qt::keepaspectratio); qwidget::resizeevent(ev); } void timerevent(qtimerevent * ev) { if (ev->timerid() != timerid) return; item->settext(qstring::number(time++)); } }; int main(int argc, char ** argv) { qapplication a(argc, argv); window window; window.show(); a.exec(); } #include "main.moc"
Comments
Post a Comment