@@ -20,6 +20,7 | |||||
20 |
|
20 | |||
21 | #include <QValuesAxis> |
|
21 | #include <QValuesAxis> | |
22 | #include <QAbstractAxis> |
|
22 | #include <QAbstractAxis> | |
|
23 | #include <cmath> | |||
23 | #include <QDebug> |
|
24 | #include <QDebug> | |
24 |
|
25 | |||
25 | #include "chart.h" |
|
26 | #include "chart.h" | |
@@ -36,22 +37,23 Chart::~Chart() | |||||
36 |
|
37 | |||
37 | void Chart::clickPoint(const QPointF &point) |
|
38 | void Chart::clickPoint(const QPointF &point) | |
38 | { |
|
39 | { | |
39 | //Get all points from the series. |
|
40 | // Find the closes data point | |
40 | QList<QPointF> points = m_series->points(); |
|
41 | m_movingPoint = QPoint(); | |
41 | //Construct a small rectangle around the clicked point |
|
42 | m_clicked = false; | |
42 | //to identify the real point clicked from the series. |
|
43 | foreach (QPointF p, m_series->points()) { | |
43 | QRectF clickRect(point.x() - 0.5, point.y() - 0.5, 1.0, 1.0); |
|
44 | if (distance(p, point) < distance(m_movingPoint, point)) { | |
44 |
|
||||
45 | //Find the clicked point to be moved. |
|
|||
46 | foreach (QPointF p, points) { |
|
|||
47 | if (clickRect.contains(p)) { |
|
|||
48 | m_movingPoint = p; |
|
45 | m_movingPoint = p; | |
49 | m_clicked = true; |
|
46 | m_clicked = true; | |
50 | return; |
|
|||
51 | } |
|
47 | } | |
52 | } |
|
48 | } | |
53 | } |
|
49 | } | |
54 |
|
50 | |||
|
51 | qreal Chart::distance(const QPointF &p1, const QPointF &p2) | |||
|
52 | { | |||
|
53 | return sqrt((p1.x() - p2.x()) * (p1.x() - p2.x()) | |||
|
54 | + (p1.y() - p2.y()) * (p1.y() - p2.y())); | |||
|
55 | } | |||
|
56 | ||||
55 | void Chart::setPointClicked(bool clicked) |
|
57 | void Chart::setPointClicked(bool clicked) | |
56 | { |
|
58 | { | |
57 | m_clicked = clicked; |
|
59 | m_clicked = clicked; |
@@ -41,6 +41,7 public: | |||||
41 | void setPointClicked(bool clicked); |
|
41 | void setPointClicked(bool clicked); | |
42 |
|
42 | |||
43 | private: |
|
43 | private: | |
|
44 | qreal distance(const QPointF &p1, const QPointF &p2); | |||
44 | QLineSeries *m_series; |
|
45 | QLineSeries *m_series; | |
45 | QPointF m_movingPoint; |
|
46 | QPointF m_movingPoint; | |
46 |
|
47 |
@@ -46,6 +46,9 int main(int argc, char *argv[]) | |||||
46 | Chart* chart = new Chart(0, 0, series); |
|
46 | Chart* chart = new Chart(0, 0, series); | |
47 | chart->legend()->hide(); |
|
47 | chart->legend()->hide(); | |
48 | chart->addSeries(series); |
|
48 | chart->addSeries(series); | |
|
49 | QPen p = series->pen(); | |||
|
50 | p.setWidth(5); | |||
|
51 | series->setPen(p); | |||
49 | chart->createDefaultAxes(); |
|
52 | chart->createDefaultAxes(); | |
50 | chart->setTitle("Drag'n drop to move data points"); |
|
53 | chart->setTitle("Drag'n drop to move data points"); | |
51 |
|
54 |
@@ -25,10 +25,9 | |||||
25 | #include <QPainter> |
|
25 | #include <QPainter> | |
26 | #include <QGraphicsSceneMouseEvent> |
|
26 | #include <QGraphicsSceneMouseEvent> | |
27 |
|
27 | |||
28 |
|
||||
29 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
28 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
30 |
|
29 | |||
31 | //TODO: optimize : remove points which are not visible |
|
30 | const qreal mouseEventMinWidth(14); | |
32 |
|
31 | |||
33 | LineChartItem::LineChartItem(QLineSeries* series,ChartPresenter *presenter): |
|
32 | LineChartItem::LineChartItem(QLineSeries* series,ChartPresenter *presenter): | |
34 | XYChart(series, presenter), |
|
33 | XYChart(series, presenter), | |
@@ -49,7 +48,13 QRectF LineChartItem::boundingRect() const | |||||
49 |
|
48 | |||
50 | QPainterPath LineChartItem::shape() const |
|
49 | QPainterPath LineChartItem::shape() const | |
51 | { |
|
50 | { | |
52 | return m_path; |
|
51 | // Increase the size of the path slightly to make mouse interactions more natural | |
|
52 | QPainterPathStroker s; | |||
|
53 | s.setCapStyle(Qt::RoundCap); | |||
|
54 | s.setJoinStyle(Qt::RoundJoin); | |||
|
55 | qreal spacing = qMax(mouseEventMinWidth, (qreal) m_linePen.width()); | |||
|
56 | s.setWidth(spacing); | |||
|
57 | return s.createStroke(m_path); | |||
53 | } |
|
58 | } | |
54 |
|
59 | |||
55 | void LineChartItem::updateGeometry() |
|
60 | void LineChartItem::updateGeometry() | |
@@ -71,8 +76,18 void LineChartItem::updateGeometry() | |||||
71 | } |
|
76 | } | |
72 |
|
77 | |||
73 | prepareGeometryChange(); |
|
78 | prepareGeometryChange(); | |
|
79 | ||||
74 | m_path = linePath; |
|
80 | m_path = linePath; | |
75 | m_rect = linePath.boundingRect(); |
|
81 | ||
|
82 | // When defining bounding rectangle, | |||
|
83 | // 1. take the line width into account (otherwise you will get drawing artifacts) and | |||
|
84 | // 2. take the shape into account (otherwise you will not get mouse events through on border | |||
|
85 | // areas). | |||
|
86 | const qreal sqrtOf2 = 1.414214; | |||
|
87 | const qreal spacing = qMax(mouseEventMinWidth / 2.0, | |||
|
88 | sqrtOf2 * (qreal) m_linePen.width() / 2.0); | |||
|
89 | m_rect = m_path.boundingRect().adjusted(-spacing, -spacing, spacing, spacing); | |||
|
90 | ||||
76 | setPos(origin()); |
|
91 | setPos(origin()); | |
77 | } |
|
92 | } | |
78 |
|
93 | |||
@@ -86,8 +101,6 void LineChartItem::handleUpdated() | |||||
86 | update(); |
|
101 | update(); | |
87 | } |
|
102 | } | |
88 |
|
103 | |||
89 | //painter |
|
|||
90 |
|
||||
91 | void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
|
104 | void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | |
92 | { |
|
105 | { | |
93 | Q_UNUSED(widget) |
|
106 | Q_UNUSED(widget) |
@@ -45,7 +45,7 class LineChartItem : public XYChart , public QGraphicsItem | |||||
45 | Q_INTERFACES(QGraphicsItem) |
|
45 | Q_INTERFACES(QGraphicsItem) | |
46 | public: |
|
46 | public: | |
47 | explicit LineChartItem(QLineSeries *series,ChartPresenter *presenter); |
|
47 | explicit LineChartItem(QLineSeries *series,ChartPresenter *presenter); | |
48 |
~LineChartItem() {} |
|
48 | ~LineChartItem() {} | |
49 |
|
49 | |||
50 | //from QGraphicsItem |
|
50 | //from QGraphicsItem | |
51 | QRectF boundingRect() const; |
|
51 | QRectF boundingRect() const; |
General Comments 0
You need to be logged in to leave comments.
Login now