Hi,
I had asked this kind of question in past but i concentrated more on QGraphicsScene::drawBackground() that time.

Here follows an example of three possible approach of drawing resistor with nodes. To test while running, select all elements of particular colour and move them together and notice difference for different colours. Obviously the last part, drawing nodes as part of component is faster. But this results in lot of book keeping for my app which I think will not be a nice trade off (sacrificing benifits of gv).

I am using the first method, where nodes are moved manually. Originally in my app I move them in scene, but for example sake I'm moving in itemChange().

My questions are:
1) Using 2nd method (NodesAsChild) doubles number of items when the components are connected. But using first method I will just have a single node for connected components where i just add a reference in nodes component list.
Will the performance decrease significantly if I use 2nd method ?

2) Are there any other ways of opimizing any of the methods further ?

3) Are there any other method of doing what I want, I mean design ?

I'm using Qt 4.2.3 on kubuntu.

Qt Code:
  1. #include <QtGui>
  2. #include <cmath>
  3.  
  4. const int NodeRadius = 3;
  5.  
  6. inline qreal distance(const QPointF& p1, const QPointF& p2)
  7. {
  8. qreal dx = p1.x() - p2.x();
  9. qreal dy = p1.y() - p2.y();
  10. return std::sqrt((dx*dx)+(dy*dy));
  11. }
  12.  
  13.  
  14. class Node : public QGraphicsItem
  15. {
  16. public:
  17. enum { Type = UserType + 1 };
  18.  
  19. Node(QGraphicsItem *parent=0, QGraphicsScene *scene=0) : QGraphicsItem(parent,scene)
  20. {
  21. setAcceptedMouseButtons(0);
  22. setFlags(0);
  23. }
  24.  
  25. QRectF boundingRect() const
  26. {
  27. return QRectF(-NodeRadius, -NodeRadius, 2*NodeRadius, 2*NodeRadius);
  28. }
  29.  
  30. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w = 0)
  31. {
  32. Q_UNUSED(o);
  33. Q_UNUSED(w);
  34. p->setRenderHints(QPainter::Antialiasing);
  35. p->setPen(Qt::darkRed);
  36. p->drawEllipse(boundingRect());
  37. }
  38.  
  39. bool contains(const QPointF& pt) const
  40. {
  41. qreal dist = distance(QPointF(0,0),pt);
  42. return (((dist * dist) - (NodeRadius*NodeRadius)) <= 0);
  43. }
  44.  
  45. bool collidesWithItem(QGraphicsItem *other) const
  46. {
  47. Node *port = qgraphicsitem_cast<Node*>(other);
  48. if(!port)
  49. return QGraphicsItem::collidesWithItem(other);
  50. qreal dist = distance(pos(),port->pos());
  51.  
  52. return (dist <= (2 * NodeRadius));
  53. }
  54.  
  55. QPainterPath shape() const
  56. {
  57. path.addEllipse(boundingRect());
  58. return path;
  59. }
  60.  
  61. int type() const
  62. {
  63. return Type;
  64. }
  65.  
  66. };
  67.  
  68. namespace SeparateNodes
  69. {
  70. class Resistor : public QGraphicsItem
  71. {
  72. public:
  73. Resistor(QGraphicsItem *parent = 0, QGraphicsScene *scene=0) : QGraphicsItem(parent,scene)
  74. {
  75. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
  76. Node *n = new Node(0,scene);
  77. n->setPos(-27.0,0.0);
  78. nodes << n;
  79. n = new Node(0,scene);
  80. n->setPos(27.0,0.0);
  81. nodes << n;
  82. }
  83.  
  84. QRectF boundingRect() const
  85. {
  86. return QRectF(-27,-9,54,18);
  87. }
  88.  
  89. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w = 0)
  90. {
  91. Q_UNUSED(o);
  92. Q_UNUSED(w);
  93. p->setPen(Qt::darkMagenta);
  94. p->drawLine(-18, -9, 18, -9);
  95. p->drawLine( 18, -9, 18, 9);
  96. p->drawLine( 18, 9,-18, 9);
  97. p->drawLine(-18, 9,-18, -9);
  98. p->drawLine(-27, 0,-18, 0);
  99. p->drawLine( 18, 0, 27, 0);
  100.  
  101. if( o->state & QStyle::State_Selected)
  102. {
  103. p->setPen(Qt::darkGray);
  104. p->drawRect(boundingRect());
  105. }
  106.  
  107. }
  108.  
  109. QVariant itemChange(GraphicsItemChange change, const QVariant &value)
  110. {
  111. if (change == ItemPositionChange && scene()) {
  112. QPointF newPos = value.toPointF();
  113. QPointF delta = newPos - pos();
  114. foreach(Node *n, nodes)
  115. n->moveBy(delta.x(), delta.y());
  116. }
  117. return QGraphicsItem::itemChange(change, value);
  118. }
  119.  
  120. QList<Node*> nodes;
  121. };
  122. }
  123.  
  124. namespace NodesAsChild
  125. {
  126. class Resistor : public QGraphicsItem
  127. {
  128. public:
  129. Resistor(QGraphicsItem *parent = 0, QGraphicsScene *scene=0) : QGraphicsItem(parent,scene)
  130. {
  131. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
  132. Node *n = new Node(this,scene);
  133. n->setPos(-27.0,0.0);
  134. n = new Node(this,scene);
  135. n->setPos(27.0,0.0);
  136. }
  137.  
  138. QRectF boundingRect() const
  139. {
  140. return QRectF(-27,-9,54,18);
  141. }
  142.  
  143. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w = 0)
  144. {
  145. Q_UNUSED(o);
  146. Q_UNUSED(w);
  147. p->setPen(Qt::darkBlue);
  148. p->drawLine(-18, -9, 18, -9);
  149. p->drawLine( 18, -9, 18, 9);
  150. p->drawLine( 18, 9,-18, 9);
  151. p->drawLine(-18, 9,-18, -9);
  152. p->drawLine(-27, 0,-18, 0);
  153. p->drawLine( 18, 0, 27, 0);
  154.  
  155. if( o->state & QStyle::State_Selected)
  156. {
  157. p->setPen(Qt::darkGray);
  158. p->drawRect(boundingRect());
  159. }
  160.  
  161. }
  162. };
  163. }
  164.  
  165. namespace NodesPartOfResistor
  166. {
  167. class Resistor : public QGraphicsItem
  168. {
  169. public:
  170. Resistor(QGraphicsItem *parent = 0, QGraphicsScene *scene=0) : QGraphicsItem(parent,scene)
  171. {
  172. setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable);
  173. }
  174.  
  175. QRectF boundingRect() const
  176. {
  177. return QRectF(-30,-12,60,24);
  178. }
  179.  
  180. void paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w = 0)
  181. {
  182. Q_UNUSED(o);
  183. Q_UNUSED(w);
  184. p->setPen(Qt::darkGreen);
  185. p->drawLine(-18, -9, 18, -9);
  186. p->drawLine( 18, -9, 18, 9);
  187. p->drawLine( 18, 9,-18, 9);
  188. p->drawLine(-18, 9,-18, -9);
  189. p->drawLine(-27, 0,-18, 0);
  190. p->drawLine( 18, 0, 27, 0);
  191.  
  192. p->setPen(Qt::darkRed);
  193. p->setRenderHints(QPainter::Antialiasing);
  194. p->drawEllipse(-27-NodeRadius,-NodeRadius,2*NodeRadius,2*NodeRadius);
  195. p->drawEllipse(27-NodeRadius,-NodeRadius,2*NodeRadius,2*NodeRadius);
  196. if( o->state & QStyle::State_Selected)
  197. {
  198. p->setPen(Qt::darkGray);
  199. p->drawRect(boundingRect());
  200. }
  201.  
  202. }
  203. };
  204. }
  205.  
  206. int main(int argc, char *argv[])
  207. {
  208. QApplication app(argc,argv);
  209. QGraphicsScene *scene = new QGraphicsScene(0.,0.,1024,768);
  210. QGraphicsView *view = new QGraphicsView(scene);
  211. view->setDragMode(QGraphicsView::RubberBandDrag);
  212. view->setAcceptDrops(true);
  213. //view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
  214. const int factor = 68;
  215. for(int i = 1; i < 11; i++)
  216. for(int j=1;j<3;j++) {
  217. SeparateNodes::Resistor *r = new SeparateNodes::Resistor(0,scene);
  218. r->setPos(100+i*factor,j*100);
  219. }
  220.  
  221. for(int i = 1; i < 11; i++)
  222. for(int j=1;j<3;j++) {
  223. NodesAsChild::Resistor *r = new NodesAsChild::Resistor(0,scene);
  224. r->setPos(100+i*factor,200+j*100);
  225. }
  226.  
  227. for(int i = 1; i < 11; i++)
  228. for(int j=1;j<3;j++) {
  229. NodesPartOfResistor::Resistor *r = new NodesPartOfResistor::Resistor(0,scene);
  230. r->setPos(100+i*factor,400+j*100);
  231. }
  232.  
  233. view->show();
  234. return app.exec();
  235. }
To copy to clipboard, switch view to plain text mode