c++ - Using QPainter to draw a line between QWidgets -


i'm working on application need able draw line between 2 qwidget objects. have tried quite few things, current attempt (which think in right direction think i'm missing something) have containing widget (which called drawwidget , holds qgridlayout qwidget objects added to) override paintevent method , call qpainter::drawline() function.

the issues i'm having that:

  1. no matter how try position of widgets, endpoints of line in wrong place
  2. whenever try draw second line, first line drew gets erased.

here paintevent function of containing widget:

void paintevent(qpaintevent *) {     if (!drewsinceupdate){         drewsinceupdate = true;         qpainter painter(this);         painter.setpen(qpen(qt::black));          painter.drawline(start->geometry().center(), end->geometry().center());     } } 

i have tried many different ways correct position of widgets in last line of paintevent, post of ways (i can't remember of them):

painter.drawline(start->pos(), end->pos()); painter.drawline(start->maptoglobal(start->geometry().center()), end->maptoglobal(end->geometry().center())); painter.drawline(this->maptoglobal(start->geometry().center()), this->maptoglobal(end->geometry().center())); painter.drawline(start->mapto(this, start->pos()), end->mapto(this, end->pos())); painter.drawline(this->mapfrom(start, start->pos()), this->mapfrom(end, end->pos())); 

and make question clear, here example of looking for, taken qt diagram scene example: example of want end getting:

what get thank can provide.

note:

-start , end both qwidget objects passed in using method

-the hierarchy relevant drawwidget is:

qmainwindow ->qscrollarea   ->drawwidget     ->qgridlayout       ->items       <-- these things want connect 

edit: make complete , verifiable example, here entirety of relevant code.

mainwindow.cpp:

#include "mainwindow.h" #include "ui_mainwindow.h" #include <qhboxlayout> #include <qvboxlayout> #include <qtextedit> #include <qpushbutton> #include <qscrollbar>  mainwindow::mainwindow(qwidget *parent) :     qmainwindow(parent),     ui(new ui::mainwindow) {     // setting relevant hierarchy      ui->setupui(this);     scrollarea = new qscrollarea();     setcentralwidget(scrollarea);      drawwidget = new drawwidget();     gridlayout = new qgridlayout();     gridlayout->setspacing(300);     drawwidget->setlayout(gridlayout);      scrollarea->setwidget(drawwidget);     scrollarea->setwidgetresizable(true);      additemslot();      qapplication::connect(scrollarea->horizontalscrollbar(), signal(rangechanged(int,int)), this, slot(scrollhorizontal())); }  // creating single 1 of example widgets want connect qwidget* mainwindow::createnewitem(){     qwidget* itemwidget = new qwidget();     itemwidget->setstylesheet("background-color: lightgray");     qhboxlayout* singleitemlayout = new qhboxlayout();     itemwidget->setlayout(singleitemlayout);      qtextedit* textedit = new qtextedit(std::to_string(counter++).c_str());     textedit->setstylesheet("background-color:white;");     singleitemlayout->addwidget(textedit);      qvboxlayout* rightsidepanel = new qvboxlayout();     rightsidepanel->setalignment(qt::aligntop);      qpushbutton* button1 = new qpushbutton("top button");      qapplication::connect(button1, signal(clicked(bool)), this, slot(additemslot()));      rightsidepanel->addwidget(button1);      qwidget* rightpanelwidget = new qwidget();     rightsidepanel->setmargin(0);     rightpanelwidget->setlayout(rightsidepanel);      singleitemlayout->addwidget(rightpanelwidget);      itemwidget->setlayout(singleitemlayout);     itemwidget->setminimumwidth(400);     itemwidget->setfixedsize(400,200);      return itemwidget; }  mainwindow::~mainwindow() {     delete ui; }  void mainwindow::scrollhorizontal() {     scrollarea->ensurewidgetvisible(noteitems.back()); }  void mainwindow::additemslot() {     qwidget* w = createnewitem();     gridlayout->addwidget(w,currrow, currcol++);     if (!noteitems.empty()){         drawwidget->updateendpoints(noteitems.back(), w);     }     noteitems.push_back(w); } 

mainwindow.h

#ifndef mainwindow_h #define mainwindow_h  #include <qgridlayout> #include <qwidget> #include <qmainwindow> #include <qscrollarea> #include <drawwidget.h> #include "drawscrollarea.h" #include <vector>  namespace ui { class mainwindow; }  class mainwindow : public qmainwindow {     q_object  public:     explicit mainwindow(qwidget *parent = 0);     ~mainwindow();  public slots:     void scrollhorizontal();     void additemslot();  private:     ui::mainwindow *ui;     qwidget* createnewitem();     int counter = 0, currcol = 0, currrow = 0;     std::vector<qwidget*> noteitems;      qscrollarea* scrollarea;     drawwidget* drawwidget;     qgridlayout* gridlayout; };  #endif // mainwindow_h 

drawwidget.cpp:

#include "drawwidget.h" #include <qdebug> #include <qrect>  drawwidget::drawwidget(qwidget *parent) : qwidget(parent) {  }  void drawwidget::paintevent(qpaintevent *) {     if (!drewsinceupdate){         drewsinceupdate = true;         qpainter painter(this);         painter.setpen(qpen(qt::black));          (connectedpair pair : items){             const qwidget* = pair.from;             const qwidget* =pair.to;              qpoint start =  from->maptoglobal(from->rect().topright() +  qpoint(0, from->height()/2));             qpoint end = to->maptoglobal(to->rect().topleft() +  qpoint(0, to->height()/2));              painter.drawline(mapfromglobal(start), mapfromglobal(end));         }     } }  void drawwidget::updateendpoints(qwidget* startin, qwidget* endin){     drewsinceupdate = false;     items.push_back(connectedpair{startin, endin}); } 

drawwidget.h

#ifndef drawwidget_h #define drawwidget_h  #include <qwidget> #include <qpainter> #include <qtcore> #include <vector>  class drawwidget : public qwidget {     q_object public:     explicit drawwidget(qwidget *parent = nullptr);     void updateendpoints(qwidget* startin, qwidget* endin);     virtual void paintevent(qpaintevent *); signals:  private:     struct connectedpair {         const qwidget* from;         const qwidget* to;     };      std::vector<connectedpair> items;     bool drewsinceupdate = true; };  #endif // drawwidget_h 

for case use function maptoglobal() , mapfromglobal(), since pos() returns position respect parent , can cause problems if widget has different parents.

drawwidget.h

#ifndef drawwidget_h #define drawwidget_h  #include <qwidget>  class drawwidget : public qwidget {     q_object public:     explicit drawwidget(qwidget *parent = nullptr);      void addwidgets(const qwidget *from, const qwidget *to);  protected:     void paintevent(qpaintevent *);  private:     struct widgetsconnected {         const qwidget* from;         const qwidget* to;     };      qlist<widgetsconnected> list;  };  #endif // drawwidget_h 

drawwidget.cpp

#include "drawwidget.h"  #include <qpainter> drawwidget::drawwidget(qwidget *parent) : qwidget(parent) { }  void drawwidget::addwidgets(const qwidget * from, const qwidget * to) {     list.append(widgetsconnected{from , to});     update(); }  void drawwidget::paintevent(qpaintevent *) {     qpainter painter(this);     for(const widgetsconnected el: list){         const qwidget* = el.from;         const qwidget* = el.to;          qpoint start =  from->maptoglobal(from->rect().topright() +  qpoint(0, from->height()/2));         qpoint end = to->maptoglobal(to->rect().topleft() +  qpoint(0, to->height()/2));          painter.drawline(mapfromglobal(start), mapfromglobal(end));     } } 

the complete example can found here.

enter image description here


Comments

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -