Solved ToolTip events not shown for recursive overlapping QGraphicsItem objects
-
Hello folks,
Newbee with event programming (and more generally GUI programming) I am in deep trouble to understand how events and signals-slots are supposed to be managed. Would you recommend some clear and basic course or wiki or book, with nice simple examples using QtGUI?
Precisely, I am presently stuck with a QGraphicsScene object on which are painted a number of QgraphicsPG objects. QgraphicsPG class is based on QGraphics item class. QgraphicsPG objects are constructed and painted recursively (tree-like) , with the same tree structure as their ptr_source member (my type Phygenic*).
I wanted to display as ToolTip some text describing the ptr_source, for instance its ptr_source->nom i.e. its name.
The QgraphicsPG sub-objects have their rectBounds rectangle inside the mother QgraphicsPG object, and they are painted after the mother QgraphicsPG object, assuming this gives them a higher Z-value (correct?) .
Neverthess, tooltip behavior is not what I expect, using the re-implemented QGraphicsPG::hoverEnterEvent as shown below:
I never see the QgraphicsPG sub-objects' ToolTip appearing inside the mother object's RectBounds , but only the mother QgraphicsPG ToolTip itself.PG_Qt_MainWindow::PG_Qt_MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::PG_Qt_MainWindow) { ui->setupUi(this); ui->graphicsView->setScene(&scene); ui->graphicsView->show() ; } //----------------------------------------------------- void PG_Qt_MainWindow::on_actionOuvrir_triggered() { QString fileName = QFileDialog::getOpenFileName(this, tr("Ouvrir le fichier..."), QString(), tr("Fichiers de modèle brut (*.pgML);") ) ; // (...) file opened and model constructed, if file is valid QGraphicsPG* item= new QGraphicsPG(ptr_modele.back(), position ) ; items.push_back(item); scene.addItem(item); } //------------------------------------------------------------------------------------------------------- QGraphicsPG::QGraphicsPG(Phygenic *ptr_pg, Indices2D position, QGraphicsItem *parent, bool develop, bool avecCalcul ) : rectBoite() , rectTexte(), texte() , flecheEntreeBoite() , flecheSortieBoite() , rectCadre(), rectBounds() { setAcceptHoverEvents(true) ; setToolTip( c_QString(" "+ptr_pg->nom) ) ; Q_UNUSED(parent) ; ptr_source= ptr_pg ; Etat_develop= develop ; boite= position ; cadre= position ; flechesInternes.clear() ; Indices2D ss_pos ; for ( int iph= 0 ; iph< ptr_source->Nph ; iph++ ) { ss_pos.iH= position.iH ; ss_pos.iV= position.iV + iph ; ss_qgpg.push_back ( new QGraphicsPG(ptr_source->ph[iph], ss_pos, this, Etat_develop, false ) ) ; // NOTE: recursive constructor is called for sub-objects. No calc for sub-objects } // next iph if (avecCalcul) calculer(boite, develop) ; } // fin de QGraphicsPG::QGraphicsPG(Phygenic *ptr_pg, QGraphicsItem *parent, bool develop) //-------------------------- void QGraphicsPG::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if ( !Etat_develop || ptr_source->Nph== 0 ) { // boite painter->setBrush(brush); painter->setPen(noir); painter->drawRect(rectBoite) ; // (...) // sous-boites if (Etat_develop) { for ( int iph= 0 ; iph< ptr_source->Nph ; iph++ ) ss_qgpg.at(iph)->paint(painter, option, widget) ; // NOTE: paint function is called recursively here for sub-objects, after the paint operations on the mother object. } // end if (Etat_develop) } // fin de QGraphicsPG::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) //------------------- void QGraphicsPG::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { QToolTip::showText(event->screenPos(), c_QString(" "+ptr_source->nom) ) ; } // fin de: void QGraphicsPG::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Apparently, no hoverEnterEvent is triggered for the sub-objects QGraphicsPG although they should be painted on top of the mother object. What did I miss?
-
Hi
I cant answer for the HoverEvent but i wondered if you checked withhttp://doc.qt.io/qt-5/qgraphicsitem.html#sceneEvent
and
if (event->type() == QEvent::ToolTip) { .... } -
@mrjj
Following your suggestion, this is what I tried :bool QGraphicsPG::sceneEvent(QEvent *event) { bool retour= false ; if (event->type() == QEvent::ToolTip) { QToolTip::showText(event->screenPos(), c_QString(" "+ptr_source->nom) ) ; retour= true ; } // end if return retour ; } // fin de: QGraphicsPG::sceneEvent(QEvent *event)
But it won't compile since event->screenPos() is not defined, apparently. Should I cast event somehow (static or dynamic?) to be able to compile.
But may be I should not re-implement any event handler and let Qt do the work for me, (since QToolTip being set in the constructor, everything else should work automatically)? So I tried and removed all specific event handlers from this class, but the result is event worse: there is no longer any ToolTip text displayed...
-
@TGVF
Finally, I nailed my bug:
I added what was missing e.g.construction of the base object in the QGraphicsPG constructor, with : QGraphicsItem(parent) instead of declaring Q_USED (parent) .QGraphicsPG::QGraphicsPG(Phygenic *ptr_pg, Indices2D position, QGraphicsItem *parent, bool develop, bool avecCalcul ) : QGraphicsItem(parent) , rectBoite() , rectTexte(), texte() , flecheEntreeBoite() , flecheSortieBoite() , rectCadre(), rectBounds() { //setAcceptHoverEvents(true) ; setToolTip( c_QString(" "+ptr_pg->nom) ) ; //Q_UNUSED(parent) ; (...)
I also changed the default value of parent to 0 instead of NULL pointer, since the documentation says =0 (isn't it the same, actually?).
public: QGraphicsPG(Phygenic* ptr_pg, Indices2D position, QGraphicsItem *parent = 0, bool develop= true, bool avecCalcul= true );
Finally, ToolTip works as desired without need for a hoverEnterEvent handler, nor any other specific event handler!
I feel better now, thanks! -
Hi
Super you found it.
Yes using 0 or NULL is the same.
If you want use something else beside 0 or NULL , then use std::nullptr