Guest User

Simple Qt graph widget

a guest
Mar 30th, 2010
1,018
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.42 KB | None | 0 0
  1. // graphwidget.h
  2. #ifndef GRAPHWIDGET_H
  3. #define GRAPHWIDGET_H
  4.  
  5. #include <QtGui/QWidget>
  6. #include <QtGui/QPainter>
  7. #include <QtCore/QVector>
  8. #include <QtCore/QPointF>
  9. #include <QtCore/QSet>
  10. #include <QtGui/QMouseEvent>
  11. #include <QtCore/QTime>
  12. #include <QtCore/QDebug>
  13. #include <cmath>
  14.  
  15. class Path {
  16.         QVector < QPointF > v_data;
  17.         QColor s_color;
  18.     public:
  19.         inline QColor color() { return s_color; }
  20.         inline void setColor(QColor clr) { s_color = clr; }
  21.         inline QVector < QPointF > data() { return v_data; }
  22.         inline QPointF& operator[] (int i) { return v_data[i]; }
  23.         inline void addPoint(const QPointF& pnt) { v_data.append(pnt); }
  24.         inline int size() { return v_data.size(); }
  25.         void resize(int size) { v_data.resize(size); }
  26.         Path(const QVector<double> &x, const QVector<double> &y);
  27.         Path();
  28. };
  29.  
  30. class GraphWidget : public QWidget
  31. {
  32.     QSet <Path*> paths;
  33.     QPointF trans;
  34.     double s_scale;
  35.     QPoint prevPos;
  36. protected:
  37.     virtual void paintEvent(QPaintEvent*);
  38.     virtual void mouseMoveEvent ( QMouseEvent *);
  39.     virtual void mousePressEvent ( QMouseEvent *);
  40.     virtual void mouseDoubleClickEvent ( QMouseEvent *);
  41.     virtual void keyPressEvent(QKeyEvent *);
  42.     virtual void wheelEvent(QWheelEvent*);
  43. public:
  44.     static const int defaultScale = 40;
  45.     static const int maxScale = 100;
  46.     static const int minScale = 3;
  47.  
  48.     inline int xToCanvX(double a_x) { return a_x*s_scale + trans.x() + width()/2; }
  49.     inline int yToCanvY(double a_y) { return -a_y*s_scale + trans.y() + height()/2; }
  50.     inline double canvXToDec(int a_x) { return (a_x - trans.x() - width()/2)/s_scale; }
  51.     inline double canvYToDec(int a_y) { return (-a_y + trans.y() + height()/2)/s_scale; }
  52.     inline double minX() { return canvXToDec(0); }
  53.     inline double maxX() { return canvXToDec(width()); }
  54.     inline void setScale(double s) { if (s>minScale && s<maxScale) s_scale = s; }
  55.     inline double scale() { return s_scale; }
  56.     bool addPath(Path* p);
  57.     Path* takePath(Path* p);
  58.     void clearPaths(bool del = false);
  59.     inline int pathCount() { return paths.size(); }
  60.     GraphWidget(QWidget *parent=NULL);
  61. };
  62.  
  63. #endif // GRAPHWIDGET_H
  64.  
  65. // graphwidget.cpp
  66. #include "graphwidget.h"
  67.  
  68. Path::Path(const QVector<double> &x, const QVector<double> &y)
  69. {
  70.     Path();
  71.     int N = std::min(x.size(), y.size());
  72.     for (int i=0; i<=N; i++)
  73.     {
  74.         v_data.append(QPointF(x[i], y[i]));
  75.     }
  76. }
  77.  
  78. Path::Path() : s_color(Qt::red)
  79. {
  80. }
  81.  
  82. GraphWidget::GraphWidget(QWidget *parent/*=NULL*/) : QWidget(parent), trans(0, 0), s_scale(defaultScale)
  83. {
  84.     setFocusPolicy(Qt::StrongFocus);
  85. }
  86.  
  87. bool GraphWidget::addPath(Path* p)
  88. {
  89.     if (!paths.contains(p))
  90.     {
  91.         paths.insert(p);
  92.         return true;
  93.     }
  94.     else
  95.         return false;
  96. }
  97.  
  98. Path* GraphWidget::takePath(Path *p)
  99. {
  100.     paths.remove(p);
  101.     return p;
  102. }
  103.  
  104. void GraphWidget::clearPaths(bool del /* = no */)
  105. {
  106.     if (del)
  107.         foreach (Path* p, paths)
  108.             delete p;
  109.     paths.clear();
  110. }
  111.  
  112. void GraphWidget::paintEvent(QPaintEvent *event)
  113. {
  114.     QTime t; t.start();
  115.  
  116.     QPainter p(this);
  117.  
  118.     p.fillRect(this->rect(), Qt::white);
  119.     p.drawLine( 0, height()/2 + trans.y(), width(),  height()/2 + trans.y() );
  120.     p.drawLine( width()/2 + trans.x(), 0, width()/2 + trans.x(), height() );
  121.  
  122.     int i;
  123.     int dash3;
  124.     const int dashL=3;
  125.     int dashF=height()/2 - dashL/2 + trans.y();
  126.     int dashT=dashF+dashL;
  127.     int maxp = ceil(canvXToDec(width()));
  128.     for (i=floor(canvXToDec(0)); i <= maxp ; i++)
  129.     {
  130.         dash3 = xToCanvX(i);
  131.         p.drawLine(dash3, dashF, dash3, dashT);
  132.         p.drawText(dash3, dashF, QString::number(i));
  133.     }
  134.  
  135.     dashF = width()/2 - dashL/2 + trans.x();
  136.     dashT = dashF+dashL;
  137.     maxp = ceil(canvYToDec(0));
  138.     int toI = std::min(maxp, -1);
  139.     for (i=floor(canvYToDec(height())); i <= toI; i++)
  140.     {
  141.         dash3 = yToCanvY(i);
  142.         p.drawLine(dashF, dash3, dashT, dash3);
  143.         p.drawText(dashT, dash3, QString::number(i));
  144.     }
  145.     for (i=std::min(maxp+1, 1); i <= maxp; i++) // longer, but i don't want "if" here
  146.     {
  147.         dash3 = yToCanvY(i);
  148.         p.drawLine(dashF, dash3, dashF+dashL, dash3);
  149.         p.drawText(dashF+dashL, dash3, QString::number(i));
  150.     }
  151.  
  152.     QPointF fr, to;
  153.     p.setRenderHint(QPainter::Antialiasing, true);
  154.     foreach (Path *path, paths)
  155.     {
  156.         if (path->size()<=0)
  157.             break;
  158.  
  159.         p.setPen(path->color());
  160.         for (i=1; i<path->size(); i++)
  161.         {
  162.             p.drawLine( xToCanvX((*path)[i-1].x()), yToCanvY((*path)[i-1].y()),
  163.                         xToCanvX((*path)[i].x()), yToCanvY((*path)[i].y()) );
  164.         }
  165.     }
  166.     p.end();
  167.     qDebug() << "Render time: " << t.elapsed();
  168. }
  169.  
  170. void GraphWidget::mousePressEvent(QMouseEvent *event)
  171. {
  172.     prevPos = event->pos();
  173. }
  174.  
  175. void GraphWidget::mouseMoveEvent(QMouseEvent *event)
  176. {
  177.     trans += event->pos() - prevPos;
  178.     prevPos = event->pos();
  179.     repaint();
  180. }
  181.  
  182. void GraphWidget::mouseDoubleClickEvent(QMouseEvent *event)
  183. {
  184.     trans.setX(0);
  185.     trans.setY(0);
  186.     s_scale = defaultScale;
  187.     repaint();
  188. }
  189.  
  190. void GraphWidget::keyPressEvent(QKeyEvent *event)
  191. {
  192.     double oldscale = s_scale;
  193.     switch (event->key())
  194.     {
  195.         case Qt::Key_Plus:
  196.             setScale(s_scale * 1.5);break;
  197.         case Qt::Key_Minus:
  198.             setScale(s_scale/1.5);break;
  199.         case Qt::Key_0:
  200.             s_scale = defaultScale;
  201.             trans.setX(0);
  202.             trans.setY(0);
  203.             break;
  204.         case Qt::Key_Up:
  205.             trans.setY(trans.y()-10);break;
  206.         case Qt::Key_Down:
  207.             trans.setY(trans.y()+10);break;
  208.         case Qt::Key_Left:
  209.             trans.setX(trans.x()-10);break;
  210.         case Qt::Key_Right:
  211.             trans.setX(trans.x()+10);break;
  212.     }
  213.     if (oldscale != s_scale)
  214.         repaint();
  215. }
  216.  
  217. void GraphWidget::wheelEvent(QWheelEvent *e)
  218. {
  219.     setScale(s_scale*std::pow(1.5, e->delta() / 100));
  220.     repaint();
  221. }
Advertisement
Add Comment
Please, Sign In to add comment