├── lib
└── Graph.lib
├── projects
├── Test
│ ├── res
│ │ └── Test.qrc
│ ├── src
│ │ ├── main_window.cpp
│ │ ├── main.cpp
│ │ ├── main_window.h
│ │ └── main_window.ui
│ ├── Test.vcxproj.filters
│ └── Test.vcxproj
└── Graph
│ ├── src
│ ├── chart
│ │ ├── axis_config.cpp
│ │ ├── chart_config.cpp
│ │ ├── series_config.cpp
│ │ ├── axis_config.h
│ │ ├── series_config.h
│ │ ├── chart_config.h
│ │ ├── series_config.ui
│ │ ├── table.h
│ │ ├── color_plot.h
│ │ ├── line_plot.h
│ │ ├── pie_plot.h
│ │ ├── scatter_plot.h
│ │ ├── tool_tip.h
│ │ ├── density_plot.h
│ │ ├── pareto_plot.h
│ │ ├── bar_plot.h
│ │ ├── color_bar.h
│ │ ├── stock_plot.h
│ │ ├── radial_plot.h
│ │ ├── qq_plot.h
│ │ ├── probability_plot.h
│ │ ├── plot.h
│ │ ├── pie_plot.cpp
│ │ ├── histogram_plot.h
│ │ ├── interval_plot.h
│ │ ├── boxbar_plot.h
│ │ ├── chart_view.h
│ │ ├── bar_plot.cpp
│ │ ├── radar_plot.h
│ │ ├── data.h
│ │ ├── radial_plot..cpp
│ │ ├── line_plot.cpp
│ │ ├── waterfall_plot.h
│ │ ├── scatter_plot.cpp
│ │ ├── color_plot.cpp
│ │ ├── table.cpp
│ │ ├── density_plot.cpp
│ │ ├── pareto_plot.cpp
│ │ ├── SizeGripItem.h
│ │ ├── plot.cpp
│ │ ├── interval_plot.cpp
│ │ ├── radar_plot.cpp
│ │ ├── boxbar_plot.cpp
│ │ ├── qq_plot.cpp
│ │ ├── tool_tip.cpp
│ │ ├── probability_plot.cpp
│ │ ├── waterfall_plot.cpp
│ │ ├── histogram_plot.cpp
│ │ ├── stock_plot.cpp
│ │ ├── SizeGripItem.cpp
│ │ ├── color_bar.cpp
│ │ ├── chart_view.cpp
│ │ └── chart_config.ui
│ ├── graph_global.h
│ ├── util
│ │ ├── math_define.h
│ │ ├── util.h
│ │ └── util.cpp
│ └── graph
│ │ ├── graphics_item.cpp
│ │ ├── graphics_item.h
│ │ ├── poly_line.h
│ │ ├── poly_line_preview.h
│ │ ├── chart_view_preview.h
│ │ ├── poly_line_preview.cpp
│ │ ├── chart_view_preview.cpp
│ │ └── poly_line.cpp
│ ├── Graph.vcxproj.filters
│ └── Graph.vcxproj
├── Chart.sln
├── README.md
├── .gitattributes
└── .gitignore
/lib/Graph.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haomehaode/QtChart/HEAD/lib/Graph.lib
--------------------------------------------------------------------------------
/projects/Test/res/Test.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/projects/Test/src/main_window.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haomehaode/QtChart/HEAD/projects/Test/src/main_window.cpp
--------------------------------------------------------------------------------
/projects/Test/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "main_window.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.showMaximized();
9 | return a.exec();
10 | }
11 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/axis_config.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "axis_config.h"
4 |
5 | AxisConfig::AxisConfig(QWidget *parent)
6 | : QDialog(parent)
7 | {
8 | ui.setupUi(this);
9 | }
10 |
11 | AxisConfig::~AxisConfig()
12 | {
13 | }
14 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/chart_config.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "chart_config.h"
4 |
5 | ChartConfig::ChartConfig(QWidget *parent)
6 | : QDialog(parent)
7 | {
8 | ui.setupUi(this);
9 | }
10 |
11 | ChartConfig::~ChartConfig()
12 | {
13 | }
14 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/series_config.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "series_config.h"
4 |
5 | SeriesConfig::SeriesConfig(QWidget *parent)
6 | : QDialog(parent)
7 | {
8 | ui.setupUi(this);
9 | }
10 |
11 | SeriesConfig::~SeriesConfig()
12 | {
13 | }
14 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph_global.h:
--------------------------------------------------------------------------------
1 | #ifndef GRAPH_GLOBAL_H
2 | #define GRAPH_GLOBAL_H
3 |
4 | #include
5 |
6 | #ifndef BUILD_STATIC
7 | # if defined(GRAPH_LIB)
8 | # define GRAPH_EXPORT Q_DECL_EXPORT
9 | # else
10 | # define GRAPH_EXPORT Q_DECL_IMPORT
11 | # endif
12 | #else
13 | # define GRAPH_EXPORT
14 | #endif
15 |
16 | #endif // GRAPH_GLOBAL_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/axis_config.h:
--------------------------------------------------------------------------------
1 | #ifndef AXIS_CONFIG_H
2 | #define AXIS_CONFIG_H
3 |
4 | #include
5 | #include "ui_axis_config.h"
6 |
7 | class AxisConfig : public QDialog
8 | {
9 | Q_OBJECT
10 |
11 | public:
12 | AxisConfig(QWidget *parent = Q_NULLPTR);
13 | ~AxisConfig();
14 |
15 | private:
16 | Ui::AxisConfig ui;
17 | };
18 |
19 | #endif // AXIS_CONFIG_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/series_config.h:
--------------------------------------------------------------------------------
1 | #ifndef SERIES_CONFIG_H
2 | #define SERIES_CONFIG_H
3 |
4 | #include
5 | #include "ui_series_config.h"
6 |
7 | class SeriesConfig : public QDialog
8 | {
9 | Q_OBJECT
10 |
11 | public:
12 | SeriesConfig(QWidget *parent = Q_NULLPTR);
13 | ~SeriesConfig();
14 |
15 | private:
16 | Ui::SeriesConfig ui;
17 | };
18 |
19 | #endif // SERIES_CONFIG_H
--------------------------------------------------------------------------------
/projects/Graph/src/util/math_define.h:
--------------------------------------------------------------------------------
1 | #ifndef MATH_DEFINE_H
2 | #define MATH_DEFINE_H
3 |
4 | /** Π 和 2Π */
5 | #define PI 3.141592653589793
6 | #define PIx2 6.283185307179586
7 |
8 | /** 公差,作为临界值 */
9 | #define TOLERANCE 1.0e-5
10 |
11 | /** 一弧度等于多少度 */
12 | #define ARAD 57.29577951308232
13 |
14 | /** 一度等于多少弧度 */
15 | #define ADEGREE 0.0174532925199433
16 |
17 | #endif // MATH_DEFINE_H
18 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/chart_config.h:
--------------------------------------------------------------------------------
1 | #ifndef CHART_CONFIG_H
2 | #define CHART_CONFIG_H
3 |
4 | #include
5 | #include "ui_chart_config.h"
6 | #include "graph_global.h"
7 |
8 | class GRAPH_EXPORT ChartConfig : public QDialog
9 | {
10 | Q_OBJECT
11 |
12 | public:
13 | ChartConfig(QWidget *parent = Q_NULLPTR);
14 | ~ChartConfig();
15 |
16 | private:
17 | Ui::ChartConfig ui;
18 | };
19 |
20 | #endif // CHART_CONFIG_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/series_config.ui:
--------------------------------------------------------------------------------
1 |
2 | SeriesConfig
3 |
4 |
5 | SeriesConfig
6 |
7 |
8 |
9 | 0
10 | 0
11 | 400
12 | 300
13 |
14 |
15 |
16 | SeriesConfig
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph/graphics_item.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "graphics_item.h"
4 | #include "chart_view.h"
5 |
6 | GraphicsItem::GraphicsItem()
7 | {
8 |
9 | }
10 |
11 | void GraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
12 | {
13 | apply();
14 | painter->setRenderHint(QPainter::Antialiasing, true);
15 | on_paint(painter);
16 | }
17 |
18 | void GraphicsItem::apply()
19 | {
20 | on_apply();
21 | }
22 |
23 | void GraphicsItem::set_view(ChartView* view)
24 | {
25 | m_view = view;
26 | }
27 |
28 | ChartView* GraphicsItem::view()
29 | {
30 | return m_view;
31 | }
32 |
33 | QRectF GraphicsItem::boundingRect() const
34 | {
35 | return QRectF(0, 0, 1, 1);
36 | }
37 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/table.h:
--------------------------------------------------------------------------------
1 | #ifndef TABLE_H
2 | #define TABLE_H
3 |
4 | #include "graph_global.h"
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | class GRAPH_EXPORT Table : public QWidget
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 |
16 | Table(QWidget* parent = nullptr);
17 |
18 | ~Table();
19 |
20 | public:
21 |
22 | void add_data(QList& list, const QString& name);
23 |
24 | void add_data(QList& list, const QString& name);
25 |
26 | void add_data(QList& list, const QString& name);
27 |
28 | void delete_data(const QString& name);
29 |
30 | private:
31 |
32 | QTableWidget* m_table = nullptr;
33 |
34 | QStringList m_head_list;
35 |
36 | };
37 |
38 | #endif // TABLE_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/color_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef COLOR_PLOT_H
2 | #define COLOR_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 |
10 | class ColorBar;
11 |
12 | class GRAPH_EXPORT ColorPlot : public Plot
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 |
18 | ColorPlot(QWidget* parent = nullptr);
19 |
20 | ~ColorPlot();
21 |
22 | public:
23 |
24 | void set_data(QList& value_list);
25 |
26 | void clear_data();
27 |
28 | virtual void init_chart() override;
29 |
30 | virtual void init_axis() override;
31 |
32 | virtual void init_series() override;
33 |
34 | private:
35 | /** 颜色条 */
36 | ColorBar* m_color_item = nullptr;
37 | /** X 轴 */
38 | QValueAxis* m_axisX = nullptr;
39 | /** Y 轴 */
40 | QValueAxis* m_axisY = nullptr;
41 | /** Z 值和散点 */
42 | QMap value2series;
43 | };
44 |
45 | #endif // COLOR_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/line_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef LINE_PLOT_H
2 | #define LINE_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include
7 | #include
8 | #include
9 |
10 | class GRAPH_EXPORT LinePlot : public Plot
11 | {
12 |
13 | public:
14 |
15 | LinePlot(QWidget *parent = Q_NULLPTR);
16 |
17 | ~LinePlot();
18 |
19 | public:
20 |
21 | void add_line(QList& poslist, const QString &name );
22 |
23 | void delete_line(const QString& name);
24 |
25 | virtual void init_chart() override;
26 |
27 | virtual void init_axis() override;
28 |
29 | virtual void init_series() override;
30 |
31 |
32 | private:
33 | /** 数据计算 */
34 | void prepare_data(QList& poslist);
35 |
36 | private:
37 | /** 名称和系列映射 */
38 | QMap m_name2series;
39 | /** X 轴 */
40 | QValueAxis* m_axisX = nullptr;
41 | /** Y 轴 */
42 | QValueAxis* m_axisY = nullptr;
43 | /** 记录坐标轴范围 */
44 | QStack m_range[4];
45 | };
46 |
47 | #endif // LINE_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/pie_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef PIE_PLOT_H
2 | #define PIE_PLOT_H
3 |
4 | #include "graph_global.h"
5 | #include "plot.h"
6 | #include "data.h"
7 | #include
8 | #include
9 |
10 |
11 | class GRAPH_EXPORT PiePlot : public Plot
12 | {
13 | Q_OBJECT
14 |
15 | public:
16 |
17 | PiePlot(QWidget* parent = nullptr);
18 |
19 | ~PiePlot();
20 |
21 | public slots:
22 | /** 鼠标提示 */
23 | virtual void slot_tool_tip(QPieSlice* slice, bool state);
24 |
25 | public:
26 |
27 | void set_data(QList& valuelist);
28 |
29 | void add_pie(double value, const QString& name);
30 |
31 | void delete_pie(const QString& name);
32 |
33 | virtual void init_chart() override;
34 |
35 | virtual void init_axis() override;
36 |
37 | virtual void init_series() override;
38 |
39 | private:
40 |
41 | void update_label();
42 |
43 | private:
44 | /** 名称和系列映射 */
45 | QMap m_name2series;
46 |
47 | QPieSeries* m_series = nullptr;
48 |
49 | };
50 |
51 | #endif // PIE_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/scatter_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef SCATTER_PLOT_H
2 | #define SCATTER_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include
7 | #include
8 | #include
9 |
10 | class GRAPH_EXPORT ScatterPlot: public Plot
11 | {
12 |
13 | public:
14 |
15 | ScatterPlot(QWidget* parent = nullptr);
16 |
17 | ~ScatterPlot();
18 |
19 | public:
20 |
21 | void add_scatter(QList& poslist, const QString& name);
22 |
23 | void delete_scatter(const QString& name);
24 |
25 | virtual void init_chart() override;
26 |
27 | virtual void init_axis() override;
28 |
29 | virtual void init_series() override;
30 |
31 | private:
32 | /** 数据计算 */
33 | void prepare_data(QList& poslist);
34 |
35 | private:
36 | /** 名称和系列映射 */
37 | QMap m_name2series;
38 | /** X 轴 */
39 | QValueAxis* m_axisX = nullptr;
40 | /** Y 轴 */
41 | QValueAxis* m_axisY = nullptr;
42 | /** 记录坐标轴范围 */
43 | QStack m_range[4];
44 | };
45 |
46 | #endif // SCATTER_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/graph/graphics_item.h:
--------------------------------------------------------------------------------
1 | #ifndef GRAPHICS_ITEM_H
2 | #define GRAPHICS_ITEM_H
3 |
4 | #include "QGraphicsItem"
5 | #include "graph_global.h"
6 |
7 | class ChartView;
8 |
9 | class GRAPH_EXPORT GraphicsItem : public QGraphicsObject
10 | {
11 | public:
12 | /** 构造函数 */
13 | GraphicsItem();
14 | /** 设置所属视图 */
15 | void set_view(ChartView* view);
16 | /** 获取所属视图 */
17 | ChartView* view();
18 | /**
19 | * 图元数据变更时可手动调用该接口以应用新的数据,
20 | * 图元绘制前会自动调用该接口以便显示正确的形状。
21 | */
22 | void apply();
23 |
24 | protected:
25 | /** 绘图区域 */
26 | virtual QRectF boundingRect() const override;
27 | /** 绘图函数 */
28 | virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
29 | /** 克隆,由子类实现 */
30 | virtual GraphicsItem* clone() { return nullptr; }
31 | /** 数据更新计算包围盒,由子类实现 */
32 | virtual void on_apply() {}
33 | /** 绘制图像,由子类实现 */
34 | virtual void on_paint(QPainter* painter) {}
35 |
36 | private:
37 | /** 所属视图 */
38 | ChartView* m_view = nullptr;
39 | };
40 |
41 | #endif // GRAPHICS_ITEM_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/tool_tip.h:
--------------------------------------------------------------------------------
1 | #ifndef TOOL_TIP_H
2 | #define TOOL_TIP_H
3 |
4 | #include "graph_global.h"
5 | #include
6 | #include
7 |
8 | using namespace QtCharts;
9 |
10 | class QGraphicsSceneMouseEvent;
11 |
12 | class GRAPH_EXPORT ToolTip : public QGraphicsItem
13 | {
14 |
15 | public:
16 |
17 | ToolTip(QChart* chart, QWidget* parent = nullptr);
18 |
19 | ~ToolTip();
20 |
21 | void setText(const QString& text);
22 |
23 | void setAnchor(QPointF point);
24 |
25 | void updateGeometry();
26 |
27 | QRectF boundingRect() const;
28 |
29 | void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
30 |
31 | protected:
32 |
33 | void mousePressEvent(QGraphicsSceneMouseEvent* event);
34 |
35 | void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
36 |
37 | private:
38 |
39 | QString m_text;
40 |
41 | QRectF m_textRect;
42 |
43 | QRectF m_rect;
44 |
45 | QPointF m_anchor;
46 |
47 | QFont m_font;
48 |
49 | QChart* m_chart = nullptr;
50 |
51 | QWidget* m_widget = nullptr;
52 | };
53 |
54 | #endif // TOOL_TIP_H
--------------------------------------------------------------------------------
/projects/Test/Test.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {d43ef1c5-b190-43e0-940d-64f79ea661cc}
6 |
7 |
8 | {3cc5815c-1f83-4006-a37e-4d20fdc44e63}
9 |
10 |
11 |
12 |
13 | res
14 |
15 |
16 |
17 |
18 | src
19 |
20 |
21 | src
22 |
23 |
24 |
25 |
26 | src
27 |
28 |
29 |
30 |
31 | src
32 |
33 |
34 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/density_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef DENSITY_PLOT_H
2 | #define DENSITY_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 |
10 | class ColorBar;
11 |
12 | class GRAPH_EXPORT DensityPlot : public Plot
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 |
18 | DensityPlot(QWidget* parent = nullptr);
19 |
20 | ~DensityPlot();
21 |
22 | public:
23 |
24 | void set_data(QList& pos_list);
25 |
26 | void clear_data();
27 |
28 | virtual void init_chart() override;
29 |
30 | virtual void init_axis() override;
31 |
32 | virtual void init_series() override;
33 |
34 | private:
35 |
36 | double squareDistance(DensityPoint a, DensityPoint b);
37 |
38 | void calculateDensity(QVector& dataset, float Eps);
39 |
40 |
41 | private:
42 | /** 颜色条 */
43 | ColorBar* m_color_item = nullptr;
44 | /** X 轴 */
45 | QValueAxis* m_axisX = nullptr;
46 | /** Y 轴 */
47 | QValueAxis* m_axisY = nullptr;
48 | /** 密度值和散点 */
49 | QMap value2series;
50 | /** 密度半径 */
51 | double radius = 1;
52 | };
53 |
54 | #endif // DENSITY_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/graph/poly_line.h:
--------------------------------------------------------------------------------
1 | #ifndef POLY_LINE_H
2 | #define POLY_LINE_H
3 |
4 | #include "chart_view.h"
5 | #include "graphics_item.h"
6 |
7 | ///////////////////////////////////////////////////////////////////////////////
8 | //多段线
9 | class PolyLine : public GraphicsItem
10 | {
11 | public:
12 |
13 | PolyLine();
14 |
15 | public:
16 |
17 | QList get_points() const;
18 |
19 | void set_points(const QList& points);
20 |
21 | void append_point(const QPointF& point);
22 |
23 | QPointF get_last_point() const;
24 |
25 | void set_last_point(const QPointF& point);
26 |
27 | virtual GraphicsItem* clone() override;
28 |
29 | protected:
30 |
31 | QRectF boundingRect() const override;
32 |
33 | void on_paint(QPainter* painter) override;
34 |
35 | protected:
36 |
37 | QList m_points;
38 |
39 | };
40 |
41 | ///////////////////////////////////////////////////////////////////////////////
42 | //箭头线
43 | class Arrows : public PolyLine
44 | {
45 | public:
46 |
47 | Arrows();
48 |
49 | virtual GraphicsItem* clone() override;
50 |
51 | protected:
52 |
53 | void on_paint(QPainter* painter) override;
54 | };
55 |
56 |
57 | #endif // POLY_LINE_H
58 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/pareto_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef PARETO_PLOT_H
2 | #define PARETO_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | class GRAPH_EXPORT ParetoPlot : public Plot
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 |
20 | ParetoPlot(QWidget *parent=nullptr);
21 |
22 | ~ParetoPlot();
23 |
24 | public:
25 |
26 | void set_data(QList& value_list);
27 |
28 | void clear_data();
29 |
30 | virtual void init_chart() override;
31 |
32 | virtual void init_axis() override;
33 |
34 | virtual void init_series() override;
35 |
36 | private:
37 | /** 数据计算 */
38 | QList& prepare_data(QList& value_list);
39 |
40 | private:
41 |
42 | QBarCategoryAxis* m_axisX = nullptr;
43 |
44 | QValueAxis* m_axisY_1 = nullptr;
45 |
46 | QValueAxis* m_axisY_2 = nullptr;
47 |
48 | QBarSeries* m_bar = nullptr;
49 |
50 | QBarSet* m_set = nullptr;
51 |
52 | QLineSeries* m_line = nullptr;
53 |
54 | QScatterSeries* m_scatter = nullptr;
55 |
56 | QStringList m_axisy_list;
57 | };
58 |
59 | #endif // PARETO_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/bar_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef BAR_PLOT_H
2 | #define BAR_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | class GRAPH_EXPORT BarPlot : public Plot
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 |
20 | BarPlot(QWidget* parent = nullptr);
21 |
22 | ~BarPlot();
23 |
24 | public:
25 |
26 | void set_axis(QList list);
27 |
28 | void add_bar(QList& value_list, const QString& name);
29 |
30 | void delete_bar(const QString& name);
31 |
32 | virtual void init_chart() override;
33 |
34 | virtual void init_axis() override;
35 |
36 | virtual void init_series() override;
37 |
38 |
39 | private:
40 | /** 数据计算 */
41 | void prepare_data(QList& value_list);
42 |
43 | private:
44 | /** 名称和系列映射 */
45 | QMap m_name2series;
46 |
47 | QBarSeries* m_series = nullptr;
48 | /** X 轴刻度集合 */
49 | QStringList m_axisx_list;
50 | /** X 轴 */
51 | QBarCategoryAxis* m_axisX =nullptr;
52 | /** Y 轴 */
53 | QValueAxis* m_axisY = nullptr;
54 | /** 记录坐标轴范围 */
55 | QStack m_range[2];
56 |
57 | };
58 |
59 | #endif // BAR_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/color_bar.h:
--------------------------------------------------------------------------------
1 | #ifndef COLOR_BAR_H
2 | #define COLOR_BAR_H
3 |
4 | #include "chart_view.h"
5 | #include "graphics_item.h"
6 | #include
7 |
8 | enum ColorBarType
9 | {
10 | Gray,
11 | Jet,
12 | Hsv,
13 | Hot
14 | };
15 |
16 | enum LocationType
17 | {
18 | Top,
19 | Bottom,
20 | Left,
21 | Right
22 | };
23 |
24 | class ColorBar : public GraphicsItem
25 | {
26 |
27 | public:
28 |
29 | ColorBar();
30 |
31 | void set_dock_area(LocationType area);
32 |
33 | void set_value_range(double min, double max);
34 |
35 | QColor getColor(double value);
36 |
37 | void set_chart(QChart* chart);
38 |
39 | void set_type(ColorBarType type);
40 |
41 | protected:
42 |
43 | QRectF boundingRect() const override;
44 |
45 | void on_paint(QPainter* painter) override;
46 |
47 | void draw_color_bar(QPainter* painter, QRectF rect);
48 |
49 | void draw_color_title(QPainter* painter, QRectF rect);
50 |
51 | void init_colors();
52 |
53 | private:
54 |
55 | LocationType m_area = Right;
56 |
57 | double m_min = 0;
58 |
59 | double m_max = 100;
60 |
61 | QVector gray_colors;
62 |
63 | QVector jet_colors;
64 |
65 | QVector hsv_colors;
66 |
67 | QVector hot_colors;
68 |
69 | QChart* m_chart = nullptr;
70 |
71 | ColorBarType m_type = Jet;
72 | };
73 |
74 | #endif // COLOR_BAR_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/stock_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef STOCK_PLOT_H
2 | #define STOCK_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | class GRAPH_EXPORT StockPlot : public Plot
16 | {
17 |
18 | public:
19 |
20 | StockPlot(QWidget* parent = nullptr);
21 |
22 | ~StockPlot();
23 |
24 | public slots:
25 | /** 鼠标提示 */
26 | virtual void slot_tool_tip(bool status, QCandlestickSet* set);
27 |
28 | public:
29 |
30 | void add_stock(QList& data_list, const QString& name);
31 |
32 | void delete_stock(const QString& name);
33 |
34 | virtual void init_chart() override;
35 |
36 | virtual void init_axis() override;
37 |
38 | virtual void init_series() override;
39 |
40 |
41 | private:
42 | /** 数据计算 */
43 | void prepare_data(QList& data_list);
44 |
45 | private:
46 | /** 名称和系列映射 */
47 | QMap m_name2series;
48 | /** X 轴 */
49 | QBarCategoryAxis* m_axisX = nullptr;
50 | /** Y 轴 */
51 | QValueAxis* m_axisY = nullptr;
52 | /** 记录坐标轴范围 */
53 | QStack m_range[4];
54 | /** X 轴时间 */
55 | QStringList m_axisx_list;
56 | };
57 |
58 | #endif // STOCK_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/graph/poly_line_preview.h:
--------------------------------------------------------------------------------
1 | #ifndef POLYLINE_PREVIEW_H
2 | #define POLYLINE_PREVIEW_H
3 |
4 | #include "chart_view_preview.h"
5 |
6 | class PolyLine;
7 | class ChartView;
8 |
9 | //多段线预览类
10 | class PolyLinePreview : public ChartViewPreview
11 | {
12 | public:
13 | PolyLinePreview(ChartView* view);
14 |
15 | protected:
16 | /**
17 | * \brief 绘制进度推进
18 | * @param point 鼠标在场景的坐标
19 | */
20 | void on_advance_preview(QPointF& point) override;
21 |
22 | /** 完成图元绘制 */
23 | void on_finish_preview() override;
24 |
25 | /** 鼠标在图元所在的图形视图窗口中移动 */
26 | void on_mouse_move(QPointF& point) override;
27 |
28 | virtual PolyLine* new_polyline();
29 |
30 | private:
31 | /**
32 | * \brief 完成步骤操作
33 | * @param step 步骤
34 | * @param point 鼠标在场景的位置
35 | */
36 | void confirm_step(int step, QPointF& point);
37 |
38 | protected:
39 | enum StepType
40 | {
41 | START_POINT, //第一个点
42 | NEXT_POINT //后续的点
43 | };
44 |
45 | PolyLine* m_pPolyLine = nullptr;
46 | QPointF m_last_confirm_point;
47 | };
48 |
49 | ///////////////////////////////////////////////////////////////////////////////
50 | //箭头线预览类
51 | class ArrowsPreview : public PolyLinePreview
52 | {
53 |
54 | public:
55 |
56 | ArrowsPreview(ChartView* view);
57 |
58 | private:
59 |
60 | PolyLine* new_polyline() override;
61 | };
62 |
63 |
64 | #endif //!POLYLINE_PREVIEW_H
65 |
66 |
67 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/radial_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef RADIAL_PLOT_H
2 | #define RADIAL_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "data.h"
6 | #include "graph_global.h"
7 | #include
8 | #include
9 |
10 | class GRAPH_EXPORT RadialPlot : public Plot
11 | {
12 | struct RadialData
13 | {
14 | RadialData(QString name,double value, QPieSeries* pie)
15 | {
16 | m_name = name;
17 | m_value = value;
18 | m_pie = pie;
19 | };
20 | QString m_name;
21 | double m_value;
22 | QPieSeries* m_pie;
23 | };
24 |
25 | public:
26 |
27 | RadialPlot(QWidget* parent = nullptr);
28 |
29 | ~RadialPlot();
30 |
31 | public slots:
32 | /** 鼠标提示 */
33 | virtual void slot_tool_tip(QPieSlice* slice, bool state);
34 |
35 | private:
36 |
37 | void update_location();
38 |
39 | public:
40 |
41 | void set_data(QList& valuelist);
42 |
43 | void add_pie(double value, const QString& name);
44 |
45 | void delete_pie(const QString& name);
46 |
47 | virtual void init_chart() override;
48 |
49 | virtual void init_axis() override;
50 |
51 | virtual void init_series() override;
52 |
53 | private:
54 |
55 | QList m_pie_series;
56 |
57 | QPieSeries* m_series = nullptr;
58 | /** 中心圆圈大小 */
59 | double m_radial_min = 0.25;
60 | /** 外围圆圈大小 */
61 | double m_radial_max = 0.85;
62 | /** 径向长度 */
63 | double m_radial_length = 0.6;
64 |
65 | };
66 |
67 | #endif // RADIAL_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/qq_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef QQ_PLOT_H
2 | #define QQ_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include "data.h"
11 |
12 | class GRAPH_EXPORT QQPlot : public Plot
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 |
18 | QQPlot(QWidget* parent = nullptr);
19 |
20 | ~QQPlot();
21 |
22 | public slots:
23 |
24 | void slot_tool_tip(QPointF point, bool state) override;
25 |
26 | public:
27 |
28 | void add_data(QList& list, const QString& name);
29 |
30 | virtual void init_chart() override;
31 |
32 | virtual void init_axis() override;
33 |
34 | virtual void init_series() override;
35 |
36 | private:
37 | /** 数据计算 */
38 | void prepare_data(QList& list);
39 | /** 理论CDF */
40 | double calculate_cdf(int index, int n);
41 |
42 | private:
43 | /** 平均值 */
44 | double m_mean;
45 | /** 方差 */
46 | double m_variance;
47 | /** 标准差 */
48 | double m_sigma;
49 | /** 样本数 */
50 | int m_n;
51 |
52 | private:
53 |
54 | QLineSeries* m_line_center = nullptr;
55 |
56 | QLineSeries* m_line_top = nullptr;
57 |
58 | QLineSeries* m_line_bottom = nullptr;
59 |
60 | QScatterSeries* m_scatter = nullptr;
61 |
62 | QValueAxis* m_axisX = nullptr;
63 |
64 | QValueAxis* m_axisY = nullptr;
65 |
66 | QList m_probability_list;
67 |
68 | ScoreType m_score_type = Benard;
69 | };
70 |
71 | #endif // QQ_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/probability_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef PROBABILITY_PLOT_H
2 | #define PROBABILITY_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include "data.h"
11 |
12 |
13 | class GRAPH_EXPORT ProbabilityPlot : public Plot
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 |
19 | ProbabilityPlot(QWidget* parent = nullptr);
20 |
21 | ~ProbabilityPlot();
22 |
23 | public slots:
24 |
25 | void slot_tool_tip(QPointF point, bool state) override;
26 |
27 | public:
28 |
29 | void add_data(QList& list, const QString& name);
30 |
31 | virtual void init_chart() override;
32 |
33 | virtual void init_axis() override;
34 |
35 | virtual void init_series() override;
36 |
37 | protected:
38 | /** 数据计算 */
39 | void prepare_data(QList& list);
40 | /** 理论CDF */
41 | double calculate_cdf(int index, int n);
42 |
43 | protected:
44 | /** 平均值 */
45 | double m_mean;
46 | /** 方差 */
47 | double m_variance;
48 | /** 标准差 */
49 | double m_sigma;
50 | /** 样本数 */
51 | int m_n;
52 |
53 | protected:
54 |
55 | QLineSeries* m_line_center =nullptr ;
56 |
57 | QLineSeries* m_line_top = nullptr;
58 |
59 | QLineSeries* m_line_bottom = nullptr;
60 |
61 | QScatterSeries* m_scatter = nullptr;
62 |
63 | QValueAxis* m_axisX = nullptr;
64 |
65 | QCategoryAxis* m_axisY = nullptr;
66 |
67 | QList m_probability_list;
68 |
69 | ScoreType m_score_type = Benard;
70 |
71 | };
72 |
73 | #endif // PROBABILITY_PLOT_H
--------------------------------------------------------------------------------
/Chart.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32228.430
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "projects\Test\Test.vcxproj", "{8C814C96-3D0C-40C4-BF44-47EADC42B3A5}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Graph", "projects\Graph\Graph.vcxproj", "{052877BA-DD5E-4B0A-9259-62F40345A8AE}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|x64 = Debug|x64
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {8C814C96-3D0C-40C4-BF44-47EADC42B3A5}.Debug|x64.ActiveCfg = Debug|x64
17 | {8C814C96-3D0C-40C4-BF44-47EADC42B3A5}.Debug|x64.Build.0 = Debug|x64
18 | {8C814C96-3D0C-40C4-BF44-47EADC42B3A5}.Release|x64.ActiveCfg = Release|x64
19 | {8C814C96-3D0C-40C4-BF44-47EADC42B3A5}.Release|x64.Build.0 = Release|x64
20 | {052877BA-DD5E-4B0A-9259-62F40345A8AE}.Debug|x64.ActiveCfg = Debug|x64
21 | {052877BA-DD5E-4B0A-9259-62F40345A8AE}.Debug|x64.Build.0 = Debug|x64
22 | {052877BA-DD5E-4B0A-9259-62F40345A8AE}.Release|x64.ActiveCfg = Release|x64
23 | {052877BA-DD5E-4B0A-9259-62F40345A8AE}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {3A6D25EA-341D-43C1-9483-B721FA4C76E0}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph/chart_view_preview.h:
--------------------------------------------------------------------------------
1 | #ifndef CHART_VIEW_PREVIEW_H
2 | #define CHART_VIEW_PREVIEW_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | class ChartView;
9 | class QMouseEvent;
10 |
11 | /** 开始预览 */
12 | #define BEGIN_PREVIEW -1
13 |
14 | class ChartViewPreview
15 | {
16 |
17 | public:
18 |
19 | virtual ~ChartViewPreview();
20 | /** 是否正在预览 */
21 | static bool is_previewing(ChartView* view);
22 | /** 完成并退出所有的绘制 */
23 | static void finish_all(ChartView* view);
24 |
25 | static void on_mouse_move(ChartView* view, QMouseEvent* event);
26 |
27 | static void on_mouse_release(ChartView* view, QMouseEvent* event);
28 |
29 | public:
30 | /**
31 | * \brief 子类实现,绘制进度推进
32 | * @param point 鼠标在场景的坐标
33 | */
34 | virtual void on_advance_preview(QPointF& point) {}
35 | /** 子类实现,完成图元绘制 */
36 | virtual void on_finish_preview() {}
37 |
38 | protected:
39 | /** 设置数据,开始预览 */
40 | void begin_preview(ChartView* view);
41 | /**
42 | * \brief 子类实现,鼠标在所属的图形视图窗口移动
43 | * @param point 鼠标在场景的坐标
44 | */
45 | virtual void on_mouse_move(QPointF& point) {}
46 | /** 获取预览步骤 */
47 | int step() const { return m_step; }
48 | /** 设置预览步骤 */
49 | void set_step(int step);
50 |
51 | private:
52 | /** 完成绘制操作 */
53 | void finish_preview();
54 | /** 推进绘制进度 */
55 | void advance_preview(const QPoint& point);
56 | /** 鼠标在视图中移动 */
57 | void on_mouse_move(QMouseEvent* event);
58 |
59 | protected:
60 |
61 | ChartView* m_view = nullptr;
62 |
63 | private:
64 | //正在绘制的图元,key 视图, value 预览图元
65 | static QMap s_view2preview;
66 | //已完成的步骤
67 | int m_step;
68 | };
69 |
70 | #endif // CHART_VIEW_PREVIEW_H
--------------------------------------------------------------------------------
/projects/Test/src/main_window.h:
--------------------------------------------------------------------------------
1 | #ifndef MAIN_WINDOW_H
2 | #define MAIN_WINDOW_H
3 |
4 | #include
5 | #include "ui_main_window.h"
6 |
7 | class LinePlot;
8 | class ScatterPlot;
9 | class PiePlot;
10 | class ProbabilityPlot;
11 | class QQPlot;
12 | class ParetoPlot;
13 | class StockPlot;
14 | class BarPlot;
15 | class Table;
16 | class RadialPlot;
17 | class BoxBarPlot;
18 | class IntervalPlot;
19 | class ColorPlot;
20 | class DensityPlot;
21 | class RadarPlot;
22 | class HistogramPlot;
23 | class WaterfallPlot;
24 |
25 | class MainWindow : public QMainWindow
26 | {
27 | Q_OBJECT
28 |
29 | public:
30 | MainWindow(QWidget *parent = Q_NULLPTR);
31 | ~MainWindow();
32 |
33 | public slots:
34 | void slot_add_line();
35 | void slot_delete_line();
36 | void slot_draw_line();
37 | void slot_draw_arrows();
38 | void slot_vertical_splitter();
39 | void slot_horizontal_splitter();
40 | void slot_delete_splitter();
41 | void slot_add_label();
42 |
43 | private:
44 |
45 | void init_chart();
46 | private:
47 | Ui::MainWindow ui;
48 | LinePlot* line = nullptr;
49 | ScatterPlot* scatter = nullptr;
50 | PiePlot* pie = nullptr;
51 | ProbabilityPlot* probability = nullptr;
52 | QQPlot* qq = nullptr;
53 | ParetoPlot* pareto = nullptr;
54 | StockPlot* stock = nullptr;
55 | BarPlot* bar = nullptr;
56 | Table* table = nullptr;
57 | RadialPlot* radial = nullptr;
58 | BoxBarPlot* boxbar = nullptr;
59 | IntervalPlot* interval = nullptr;
60 | ColorPlot* color = nullptr;
61 | DensityPlot* density = nullptr;
62 | RadarPlot* radar = nullptr;
63 | HistogramPlot* histogram = nullptr;
64 | WaterfallPlot* waterfall = nullptr;
65 | };
66 |
67 | #endif // MAIN_WINDOW_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/plot.h:
--------------------------------------------------------------------------------
1 | #ifndef PLOT_H
2 | #define PLOT_H
3 |
4 | #include "graph_global.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | using namespace QtCharts;
12 |
13 | class ChartView;
14 | class ToolTip;
15 |
16 | class GRAPH_EXPORT Plot : public QWidget
17 | {
18 | Q_OBJECT
19 |
20 | public:
21 |
22 | Plot(bool IsPolar=false, QWidget *parent = nullptr);
23 |
24 | ~Plot();
25 |
26 | public slots:
27 | /** 鼠标提示 */
28 | virtual void slot_tool_tip(QPointF point, bool state);
29 | /** 图例点击 */
30 | void slot_handle_marker_clicked();
31 |
32 | public:
33 | /** 图表标题 */
34 | void add_title(const QString& name);
35 | /** 连接图例 */
36 | void connect_markers();
37 | /** 取消图例连接 */
38 | void disconnect_markers();
39 | /** 开始画线 */
40 | void draw_line();
41 | /** 开始画箭头 */
42 | void draw_arrows();
43 |
44 | protected:
45 | /** 初始化图表 */
46 | virtual void init_chart() = 0;
47 | /** 初始化坐标轴 */
48 | virtual void init_axis() = 0;
49 | /** 初始化系列 */
50 | virtual void init_series() = 0;
51 |
52 | protected:
53 | virtual void resizeEvent(QResizeEvent* event) override;
54 |
55 | protected:
56 | /** 图表 */
57 | QChart* m_chart = nullptr;
58 | /** 视图 */
59 | ChartView* m_chartview = nullptr;
60 | /** 鼠标提示 */
61 | ToolTip* m_tooltip = nullptr;
62 | /** X 最小值 */
63 | double m_min_x = DBL_MAX;
64 | /** X 最大值 */
65 | double m_max_x = DBL_MIN;
66 | /** Y 最小值 */
67 | double m_min_y = DBL_MAX;
68 | /** Y 最大值 */
69 | double m_max_y = DBL_MIN;
70 | /** Z 最小值 */
71 | double m_min_z = DBL_MAX;
72 | /** Z 最大值 */
73 | double m_max_z = DBL_MIN;
74 | };
75 |
76 | #endif // PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/pie_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "pie_plot.h"
4 |
5 | PiePlot::PiePlot(QWidget* parent)
6 | : Plot(parent)
7 | {
8 | init_series();
9 | init_chart();
10 | init_axis();
11 | }
12 |
13 | PiePlot::~PiePlot()
14 | {
15 | }
16 |
17 | void PiePlot::slot_tool_tip(QPieSlice* slice, bool state)
18 | {
19 | slice->setLabelVisible(state);
20 | slice->setExploded(state);
21 | }
22 |
23 | void PiePlot::set_data(QList& valuelist)
24 | {
25 | for (auto& item : valuelist)
26 | add_pie(item.m_value, item.m_name);
27 | }
28 |
29 | void PiePlot::add_pie(double value, const QString& name)
30 | {
31 | QPieSlice* pie = new QPieSlice(name , value);
32 | m_series->append(pie);
33 | m_name2series[name] = pie;
34 | update_label();
35 | }
36 |
37 | void PiePlot::delete_pie(const QString& name)
38 | {
39 | if (!m_name2series.contains(name))
40 | return;
41 | m_series->remove(m_name2series[name]);
42 | m_name2series.remove(name);
43 | }
44 |
45 | void PiePlot::init_chart()
46 | {
47 | m_chart->addSeries(m_series);
48 | m_chart->legend()->setVisible(true);
49 | m_chart->legend()->setAlignment(Qt::AlignRight);
50 | }
51 |
52 | void PiePlot::init_axis()
53 | {
54 |
55 | }
56 |
57 | void PiePlot::init_series()
58 | {
59 | m_series = new QPieSeries();
60 | connect(m_series, &QPieSeries::hovered, this, &PiePlot::slot_tool_tip);
61 | }
62 |
63 | void PiePlot::update_label()
64 | {
65 | // 设置块标签
66 | for (int sNum = 0; sNum < m_series->slices().count(); sNum++)
67 | {
68 | QPieSlice* slice = m_series->slices().at(sNum);
69 | QString tagText = QString("%1 %2%")
70 | .arg(slice->label().split(' ')[0])
71 | .arg(QString::number(slice->percentage() * 100));
72 | slice->setLabel(tagText);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/histogram_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef HISTOGRAM_PLOT_H
2 | #define HISTOGRAM_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "graphics_item.h"
7 | #include
8 | #include
9 |
10 | //////////////////////////////////////////////////////////////////////////////
11 | /// 直方图
12 | class HistogramItem :public GraphicsItem
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | HistogramItem();
18 | void set_chart(QChart* chart);
19 | void set_data(QVector data);
20 | void set_index(int index);
21 |
22 | signals:
23 | void signal_prepare_path() const;
24 |
25 | public slots:
26 | void slot_prepare_path();
27 |
28 | protected:
29 | QRectF boundingRect() const override;
30 | void on_paint(QPainter* painter) override;
31 |
32 | private:
33 | QChart* m_chart = nullptr;
34 | QVector m_data;
35 | int m_index = 0;
36 | QPainterPath m_shape;
37 | };
38 |
39 | struct Histogram
40 | {
41 | int m_index;
42 | QList m_list;
43 | QList m_value;
44 | QScatterSeries* m_series = nullptr;
45 | };
46 |
47 | class GRAPH_EXPORT HistogramPlot : public Plot
48 | {
49 | Q_OBJECT
50 |
51 | public:
52 |
53 | HistogramPlot(QWidget* parent = nullptr);
54 |
55 | ~HistogramPlot();
56 |
57 | void add_histogram(QList& value_list, const QString& name);
58 |
59 | void delete_histogram(const QString& name);
60 |
61 | protected:
62 |
63 | virtual void init_chart() override;
64 |
65 | virtual void init_axis() override;
66 |
67 | virtual void init_series() override;
68 |
69 | QList> prepare_data(QList& list);
70 |
71 |
72 | private:
73 | /** 名称和系列映射 */
74 | QMap m_name2itemlist;
75 | /** X 轴 */
76 | QValueAxis* m_axisX = nullptr;
77 | /** Y 轴 */
78 | QValueAxis* m_axisY = nullptr;
79 | /** 间距 */
80 | double m_interval = 2;
81 | /** 总数 */
82 | int m_count = 0;
83 | };
84 |
85 | #endif // HISTOGRAM_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/interval_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef INTERVAL_PLOT_H
2 | #define INTERVAL_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "data.h"
6 | #include "graph_global.h"
7 | #include "graphics_item.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | //////////////////////////////////////////////////////////////////////////////
14 | /// 间隔图
15 | class IntervalItem :public GraphicsItem
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | IntervalItem();
21 | void set_chart(QChart* chart);
22 | void set_data(BoxData& data, int index);
23 | double get_max();
24 | double get_min();
25 |
26 | signals:
27 | void signal_prepare_path() const;
28 |
29 | public slots:
30 | void slot_prepare_path();
31 |
32 | protected:
33 | QRectF boundingRect() const override;
34 | void on_paint(QPainter* painter) override;
35 |
36 | private:
37 | QChart* m_chart = nullptr;
38 | QList m_list;
39 | QString m_name;
40 | QPointF m_min ;
41 | QPointF m_max ;
42 | QPointF m_mean;
43 | QPointF m_sum ;
44 | QPainterPath m_shape;
45 | };
46 |
47 | class GRAPH_EXPORT IntervalPlot : public Plot
48 | {
49 | Q_OBJECT
50 |
51 | public:
52 |
53 | IntervalPlot(QWidget* parent = nullptr);
54 |
55 | ~IntervalPlot();
56 |
57 | public:
58 |
59 | void set_data(QList& list);
60 |
61 | void add_interval(BoxData& data, int index, double& y_min, double& y_max);
62 |
63 | virtual void init_chart() override;
64 |
65 | virtual void init_axis() override;
66 |
67 | virtual void init_series() override;
68 |
69 | private:
70 | /** 名称和系列映射 */
71 | QMap m_name2item;
72 | /** X 轴 */
73 | QBarCategoryAxis* m_axisX = nullptr;
74 | /** X 轴刻度 */
75 | QStringList m_axisx_list;
76 | /** Y 轴 */
77 | QValueAxis* m_axisY = nullptr;
78 | /** 记录坐标轴范围 */
79 | QStack m_range[4];
80 | /** 参考点 */
81 | QScatterSeries* m_series = nullptr;
82 | };
83 |
84 | #endif // INTERVAL_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/boxbar_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef BOXBAR_PLOT_H
2 | #define BOXBAR_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "graphics_item.h"
12 |
13 |
14 | //////////////////////////////////////////////////////////////////////////////
15 | /// 条形图
16 | class BoxBarItem :public GraphicsItem
17 | {
18 | Q_OBJECT
19 |
20 | public:
21 | BoxBarItem();
22 | void set_chart(QChart* chart);
23 | void set_data(double mean, double sum, double min, double max, int index);
24 |
25 | signals:
26 | void signal_prepare_path() const;
27 |
28 | public slots:
29 | void slot_prepare_path();
30 |
31 | protected:
32 | QRectF boundingRect() const override;
33 | void on_paint(QPainter* painter) override;
34 |
35 | private:
36 | QChart* m_chart = nullptr;
37 | QPointF m_min;
38 | QPointF m_max;
39 | QPointF m_mean;
40 | QPointF m_sum;
41 | QPainterPath m_shape;
42 | };
43 |
44 |
45 | class GRAPH_EXPORT BoxBarPlot : public Plot
46 | {
47 | Q_OBJECT
48 |
49 | public:
50 |
51 | BoxBarPlot(QWidget* parent = nullptr);
52 |
53 | ~BoxBarPlot();
54 |
55 | void set_type(BoxBarType type);
56 |
57 | public:
58 |
59 | void set_data(QList &list);
60 |
61 | void add_boxbar(BoxData& data, int size, int index);
62 |
63 | void delete_boxbar(const QString& name);
64 |
65 | virtual void init_chart() override;
66 |
67 | virtual void init_axis() override;
68 |
69 | virtual void init_series() override;
70 |
71 | private:
72 | /** 名称和系列映射 */
73 | QMap m_name2series;
74 | /** 名称和条形图映射 */
75 | QMap m_name2item;
76 | /** X 轴 */
77 | QBarCategoryAxis* m_axisX = nullptr;
78 | /** Y 轴 */
79 | QValueAxis* m_axisY = nullptr;
80 | /** X 轴 */
81 | QStringList m_axisx_list;
82 | /** 条形图 */
83 | QStackedBarSeries* m_series = nullptr;
84 | /** 绘画模式 */
85 | BoxBarType m_boxbartype = MEAN;
86 |
87 | };
88 |
89 | #endif // BOX_BAR_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/chart_view.h:
--------------------------------------------------------------------------------
1 | #ifndef CHART_VIEW_H
2 | #define CHART_VIEW_H
3 |
4 | #include "graph_global.h"
5 | #include "graphics_item.h"
6 |
7 | #include
8 | #include
9 |
10 |
11 | using namespace QtCharts;
12 |
13 | class GRAPH_EXPORT ChartView : public QGraphicsView
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 |
19 | ChartView(QChart* chart, QWidget* parent = nullptr);
20 |
21 | public:
22 | /** 重绘场景 */
23 | void redraw();
24 | /** \brief 保存图片*/
25 | bool save_picture(const QString& filename, const QSize& size = QSize(3050, 2050));
26 | /** 返回视图的widget */
27 | QWidget* widget();
28 | /** 智能设置视图的光标 */
29 | void set_cursor_auto();
30 | /** 将视图坐标转换到场景坐标 */
31 | QPointF map_to_scene(const QPoint& pos);
32 | /** 将场景坐标转换到视图坐标 */
33 | QPoint map_from_scene(const QPointF& pos);
34 | /** 将视图坐标转换到屏幕坐标 */
35 | QPoint map_to_global(const QPoint& pos);
36 | /** 添加图元 */
37 | void add_item(GraphicsItem* item);
38 | /** 删除图元 */
39 | void delete_item(GraphicsItem* item);
40 | /** 正在绘图 */
41 | bool is_previewing();
42 |
43 | public slots:
44 |
45 | void slot_chart_config();
46 |
47 | void slot_series_config();
48 |
49 | void slot_axis_config();
50 |
51 | protected:
52 |
53 | virtual void resizeEvent(QResizeEvent* event) override;
54 |
55 | virtual void mousePressEvent(QMouseEvent* event) override;
56 |
57 | virtual void mouseMoveEvent(QMouseEvent* event) override;
58 |
59 | virtual void mouseReleaseEvent(QMouseEvent* event) override;
60 |
61 | virtual void keyPressEvent(QKeyEvent* event) override;
62 |
63 | virtual void wheelEvent(QWheelEvent* event) override;
64 |
65 | virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
66 |
67 | private:
68 | /** 图表 */
69 | QChart* m_chart = nullptr;
70 | /** 框选开始点 */
71 | QPoint m_begin_point;
72 | /** 框选结束点 */
73 | QPoint m_end_point;
74 | /** 拖拽点 */
75 | QPoint m_old_point;
76 | /** 是否拖拽 */
77 | bool m_isTranslate = false;
78 | /** 拖拽记录*/
79 | QPointF m_translate_pos;
80 | };
81 |
82 | #endif // CHART_VIEW_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/bar_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "bar_plot.h"
4 |
5 | BarPlot::BarPlot(QWidget *parent)
6 | : Plot(parent)
7 | {
8 | init_series();
9 | init_chart();
10 | init_axis();
11 | }
12 |
13 | BarPlot::~BarPlot()
14 | {
15 |
16 | }
17 |
18 | void BarPlot::set_axis(QList list)
19 | {
20 | m_axisx_list = list;
21 | m_axisX->append(m_axisx_list);
22 | }
23 |
24 | void BarPlot::add_bar(QList& value_list, const QString& name)
25 | {
26 | if (m_name2series.contains(name))
27 | return;
28 |
29 | prepare_data(value_list);
30 |
31 | QBarSet* set = new QBarSet(name);
32 | set->append(value_list);
33 | m_series->append(set);
34 |
35 | m_name2series[name] = set;
36 |
37 | m_axisY->setRange(m_min_y - 1, m_max_y + 1);
38 |
39 | //connect(series, &QLineSeries::hovered, this, &Plot::slot_tool_tip);
40 | //connect_markers();
41 | }
42 |
43 | void BarPlot::delete_bar(const QString& name)
44 | {
45 | if (!m_name2series.contains(name))
46 | return;
47 | m_series->remove(m_name2series[name]);
48 | m_name2series.remove(name);
49 |
50 | m_range[0].pop();
51 | m_range[1].pop();
52 |
53 | m_min_y = m_range[0].top();
54 | m_max_y = m_range[1].top();
55 |
56 | m_axisY->setRange(m_min_y - 1, m_max_y + 1);
57 | }
58 |
59 | void BarPlot::init_chart()
60 | {
61 | m_chart->addSeries(m_series);
62 | }
63 |
64 | void BarPlot::init_axis()
65 | {
66 | m_axisX = new QBarCategoryAxis();
67 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
68 | m_series->attachAxis(m_axisX);
69 |
70 | m_axisY = new QValueAxis();
71 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
72 | m_series->attachAxis(m_axisY);
73 | }
74 |
75 | void BarPlot::init_series()
76 | {
77 | m_series = new QBarSeries();
78 | }
79 |
80 | void BarPlot::prepare_data(QList& value_list)
81 | {
82 | for (auto& value : value_list)
83 | {
84 | if (value < m_min_y)
85 | m_min_y = value;
86 | if (value > m_max_y)
87 | m_max_y = value;
88 | }
89 | m_range[0].push(m_min_y);
90 | m_range[1].push(m_max_y);
91 | }
92 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/radar_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef RADAR_PLOT_H
2 | #define RADAR_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "graphics_item.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | enum RadarType
14 | {
15 | Radar = 0, //雷达图
16 | Spider //蜘蛛网图
17 | };
18 |
19 | enum DrawTpye
20 | {
21 | Scatter = 0, //散点图
22 | Line, //连线图
23 | Area //区域图
24 | };
25 |
26 | //////////////////////////////////////////////////////////////////////////////
27 | /// 雷达图
28 | class RadarItem :public GraphicsItem
29 | {
30 | Q_OBJECT
31 |
32 | public:
33 | RadarItem();
34 | void set_chart(QChart* chart);
35 | void set_radial(int radial);
36 | void set_angular(int angular);
37 |
38 | protected:
39 | QRectF boundingRect() const override;
40 | void on_paint(QPainter* painter) override;
41 |
42 | private:
43 | QChart* m_chart = nullptr;
44 | /** 雷达项数 */
45 | int m_angular = 5;
46 | /** 雷达圈数 */
47 | int m_radial = 6;
48 | };
49 |
50 |
51 | class GRAPH_EXPORT RadarPlot : public Plot
52 | {
53 | Q_OBJECT
54 |
55 | public:
56 |
57 | RadarPlot(QWidget* parent = nullptr);
58 |
59 | ~RadarPlot();
60 |
61 | void set_radar(QStringList& lablelist);
62 |
63 | void add_radar(QList& valuelist, const QString& name);
64 |
65 | void delete_radar(const QString& name);
66 |
67 | void set_radar_type(RadarType type);
68 |
69 |
70 | protected:
71 |
72 | virtual void init_chart() override;
73 |
74 | virtual void init_axis() override;
75 |
76 | virtual void init_series() override;
77 |
78 | private:
79 | /** 蜘蛛网图 */
80 | RadarItem* item = nullptr;
81 | /** 角度值/雷达项 */
82 | QCategoryAxis* m_angularAxis = nullptr;
83 | /** 雷达值/雷达圈数 */
84 | QValueAxis* m_radialAxis = nullptr;
85 | /** 图类型 */
86 | RadarType m_radartype = Spider;
87 | /** 线类型 */
88 | DrawTpye m_drawtype = Line;
89 | /** 雷达项数 */
90 | int count = 0;
91 | /** 名称和系列映射 */
92 | QMap m_name2series;
93 | };
94 |
95 | #endif // RADAR_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/data.h:
--------------------------------------------------------------------------------
1 | #ifndef DATA_H
2 | #define DATA_H
3 |
4 | /** 概率结构 */
5 | struct Probability
6 | {
7 | /** 分位数 */
8 | int index;
9 | /** 理论值 */
10 | double theory;
11 | /** 理论CDF */
12 | double theory_cdf;
13 | /** 理论Z值 */
14 | double theory_z;
15 | /** 实际值 */
16 | double reality;
17 | /** 实际CDF */
18 | double reality_cdf;
19 | /** 实际Z值 */
20 | double reality_z;
21 | };
22 |
23 | /** 评分方法 */
24 | enum ScoreType
25 | {
26 | Blom,
27 | Benard,
28 | Hazen,
29 | VanDerWaerden,
30 | KaplanMeier
31 | };
32 |
33 | /** 股票图数据 */
34 | struct CandlestickData
35 | {
36 | CandlestickData(double timestamp, double open, double high, double low, double close)
37 | {
38 | m_timestamp = timestamp;
39 | m_open = open;
40 | m_high = high;
41 | m_low = low;
42 | m_close = close;
43 | }
44 | double m_timestamp;
45 | double m_open;
46 | double m_high;
47 | double m_low;
48 | double m_close;
49 | };
50 |
51 | /** 柱状图数据 */
52 | struct PieData
53 | {
54 | PieData(QString name, double value)
55 | {
56 | m_name = name;
57 | m_value = value;
58 | }
59 | QString m_name;
60 | double m_value;
61 | };
62 |
63 | /** 帕累托图数据 */
64 | struct ParetoData
65 | {
66 | ParetoData(QString name, double value)
67 | {
68 | m_name = name;
69 | m_value = value;
70 | }
71 | QString m_name;
72 | double m_value;
73 | double m_percent;
74 | };
75 |
76 | /** 3d数据 */
77 | struct ThirdDData
78 | {
79 | ThirdDData(double x, double y,double z)
80 | {
81 | m_x = x;
82 | m_y = y;
83 | m_z = z;
84 | }
85 | double m_x;
86 | double m_y;
87 | double m_z;
88 | };
89 |
90 | /** 箱型图数据 */
91 | struct BoxData
92 | {
93 | QString m_name;
94 | QList m_value_list;
95 | };
96 |
97 | /** 条形图 */
98 | enum BoxBarType
99 | {
100 | MEAN,
101 | SUM,
102 | MAX,
103 | MIN
104 | };
105 |
106 | /** 密度点 */
107 | struct DensityPoint
108 | {
109 | DensityPoint(double a, double b)
110 | {
111 | x = a;
112 | y = b;
113 | }
114 | qreal x;
115 | qreal y;
116 | int pts = 1;
117 | };
118 | #endif //DATA_H
119 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/radial_plot..cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "radial_plot.h"
4 | #include "QPieSeries"
5 |
6 | RadialPlot::RadialPlot(QWidget* parent)
7 | : Plot(parent)
8 | {
9 | init_series();
10 | init_chart();
11 | init_axis();
12 | }
13 |
14 | RadialPlot::~RadialPlot()
15 | {
16 | }
17 |
18 | void RadialPlot::slot_tool_tip(QPieSlice* slice, bool state)
19 | {
20 | slice->setLabelVisible(state);
21 | //slice->setExploded(state);
22 | }
23 |
24 | void RadialPlot::update_location()
25 | {
26 | const QStringList colorNames = QColor::colorNames();
27 | double sum = 360 / m_pie_series.size();
28 | double start = 0;
29 | for (int i=0;i< m_pie_series.size();i++)
30 | {
31 | QPieSeries* series = m_pie_series[i].m_pie;
32 |
33 | QList slices = series->slices();
34 | for (QPieSlice* slice : slices)
35 | slice->setColor(QColor(colorNames[(i+10)%148]));
36 |
37 | series->setHoleSize(m_radial_min - 0.0001);
38 | double length = m_radial_min + m_radial_length * m_pie_series[i].m_value / m_max_x;
39 | series->setPieSize(length);
40 | series->setPieStartAngle(start);
41 | start += sum;
42 | series->setPieEndAngle(start);
43 | }
44 | }
45 |
46 | void RadialPlot::set_data(QList& valuelist)
47 | {
48 | for (auto& item : valuelist)
49 | add_pie(item.m_value, item.m_name);
50 | }
51 |
52 | void RadialPlot::add_pie(double value, const QString& name)
53 | {
54 | if (value < m_min_x)
55 | m_min_x = value;
56 | if (value > m_max_x)
57 | m_max_x = value;
58 |
59 | QPieSeries* series = new QPieSeries();
60 | series->append(name + " " + QString::number(value), value);
61 | m_chart->addSeries(series);
62 | connect(series, &QPieSeries::hovered, this, &RadialPlot::slot_tool_tip);
63 |
64 | m_pie_series.append(RadialData(name, value, series));
65 |
66 | update_location();
67 | }
68 |
69 | void RadialPlot::delete_pie(const QString& name)
70 | {
71 |
72 | }
73 |
74 | void RadialPlot::init_chart()
75 | {
76 | //m_chart->legend()->setVisible(true);
77 | m_chart->legend()->setAlignment(Qt::AlignRight);
78 | }
79 |
80 | void RadialPlot::init_axis()
81 | {
82 |
83 | }
84 |
85 | void RadialPlot::init_series()
86 | {
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph/poly_line_preview.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "poly_line_preview.h"
4 |
5 | #include "util.h"
6 | #include "chart_view.h"
7 | #include "poly_line.h"
8 |
9 | PolyLinePreview::PolyLinePreview(ChartView* view)
10 | {
11 | begin_preview(view);
12 | }
13 |
14 | void PolyLinePreview::on_finish_preview()
15 | {
16 | if (m_pPolyLine != nullptr)
17 | {
18 | auto points = m_pPolyLine->get_points();
19 | points.pop_back();
20 | if (points.size() >= 2)
21 | {
22 | m_pPolyLine->set_points(points);
23 | m_view->add_item(m_pPolyLine->clone());
24 | }
25 | m_view->delete_item(m_pPolyLine);
26 | DELETE_PTR(m_pPolyLine);
27 | }
28 | }
29 |
30 | void PolyLinePreview::on_advance_preview(QPointF& point)
31 | {
32 | if (step() == BEGIN_PREVIEW)
33 | set_step(START_POINT);
34 | else if (step() == START_POINT)
35 | set_step(NEXT_POINT);
36 |
37 | confirm_step(step(), point);;
38 | }
39 |
40 | void PolyLinePreview::on_mouse_move(QPointF& point)
41 | {
42 | //将鼠标点坐标更新到直线的最后一个点
43 | if (step() >= START_POINT && step() <= NEXT_POINT)
44 | {
45 | if (QLineF(m_last_confirm_point, point).length() > 0.001)
46 | {
47 | if (m_pPolyLine->view() == nullptr)
48 | {
49 | m_pPolyLine->append_point(point);
50 | m_view->add_item(m_pPolyLine);
51 | }
52 | m_pPolyLine->set_last_point(point);
53 | }
54 | }
55 | }
56 |
57 | PolyLine* PolyLinePreview::new_polyline()
58 | {
59 | return new PolyLine();
60 | }
61 |
62 | void PolyLinePreview::confirm_step(int step, QPointF& point)
63 | {
64 | //确定第一个点
65 | if (step == START_POINT)
66 | {
67 | m_pPolyLine = new_polyline();
68 | m_pPolyLine->append_point(point);
69 | m_last_confirm_point = point;
70 | }
71 | //确定后续的点
72 | else if (step == NEXT_POINT)
73 | {
74 | if (QLineF(m_last_confirm_point, point).length() > 0.001)
75 | {
76 | m_pPolyLine->append_point(point);
77 | m_last_confirm_point = point;
78 | }
79 | }
80 | }
81 |
82 | ///////////////////////////////////////////////////////////////////////////////
83 | ///箭头线
84 | ArrowsPreview::ArrowsPreview(ChartView* view)
85 | :PolyLinePreview(view)
86 | {
87 |
88 | }
89 |
90 | PolyLine* ArrowsPreview::new_polyline()
91 | {
92 | return new Arrows();
93 | }
94 |
--------------------------------------------------------------------------------
/projects/Graph/src/util/util.h:
--------------------------------------------------------------------------------
1 | #ifndef UTIL_H
2 | #define UTIL_H
3 |
4 | #include "math_define.h"
5 | #include "graph_global.h"
6 |
7 | #include
8 | #include
9 |
10 | //宏定义:销毁指针
11 | #define DELETE_PTR(p) if(p){delete p; p = nullptr;}
12 | #define DELETE_PTR_LIST(list) { for (auto x : list) delete x; list.clear();}
13 |
14 | //宏定义:double是否相等
15 | #define DOUBLE_EQUAL(d1, d2) (fabs((d1)-(d2)) <= TOLERANCE)
16 |
17 |
18 | class GRAPH_EXPORT Util
19 | {
20 | public:
21 |
22 | static QRectF bounding_rect(const QList& points);
23 |
24 | static void bounding_rect(const QList& points, double& xmin, double& xmax, double& ymin, double& ymax);
25 |
26 | static QRectF bounding_rect(const QList& rects);
27 |
28 | static void bounding_rect(const QRectF& rect, double& xmin, double& xmax, double& ymin, double& ymax);
29 |
30 | /**
31 | * 基于x轴向右,y轴向上,逆时针为正,
32 | * 计算向量p1p2的角度,范围是[0, 360)
33 | */
34 | static double angle(const QPointF& p1, const QPointF& p2);
35 |
36 | /**
37 | * 基于x轴向右,y轴向上,逆时针为正,
38 | * 基于坐标原点旋转点p,angle的范围是[0, 360)
39 | */
40 | static QPointF rotated(const QPointF& p, double angle);
41 |
42 | /** 求平均值*/
43 | static double average(QList& list);
44 |
45 | /** 求最大值*/
46 | static double max(QList& list);
47 |
48 | /** 求最小值*/
49 | static double min(QList& list);
50 |
51 | static void cal_list(QList& list,double &mean,double &sum,double &max,double &min);
52 |
53 | /** 求方差 */
54 | //若n个数据为总体,则求总体标准差,标准差公式根号内除以n;若n个数据为样本,则求样本标准差,标准差公式根号内除以(n - 1)。
55 | static double variance(QList& list,double mean= DBL_MIN);
56 |
57 | /** 求标准差 */
58 | static double standard_deviation(QList& list,double sigma2 = DBL_MIN);
59 |
60 |
61 | //计算正态累积分布函数
62 | //https://blog.csdn.net/weixin_42112208/article/details/81292610
63 | //https://stackoverflow.com/questions/2328258/cumulative-normal-distribution-function-in-c-c
64 | //注意负号,但是算的是左侧累积量,(1-该值)*2 //这算的是标准差为1 均值为0 的
65 | static double normal_cdf(double value);
66 |
67 | static double normal_z(double value);
68 |
69 | static double normsdist(double z);
70 |
71 | static double normsinv(double p);
72 | };
73 | #endif //UTIL_H
74 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/line_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "line_plot.h"
4 | #include
5 |
6 | LinePlot::LinePlot(QWidget* parent)
7 | : Plot(parent)
8 | {
9 | init_series();
10 | init_chart();
11 | init_axis();
12 | }
13 |
14 | LinePlot::~LinePlot()
15 | {
16 | }
17 |
18 | void LinePlot::add_line(QList& poslist, const QString& name)
19 | {
20 | if (m_name2series.contains(name))
21 | return;
22 |
23 | prepare_data(poslist);
24 |
25 | QLineSeries* series = new QLineSeries();
26 | series->append(poslist);
27 | series->setName(name);
28 | m_chart->addSeries(series);
29 | m_name2series[name] = series;
30 | series->attachAxis(m_axisX);
31 | series->attachAxis(m_axisY);
32 | m_axisX->setRange(m_min_x, m_max_x);
33 | m_axisY->setRange(m_min_y, m_max_y);
34 |
35 | connect(series, &QLineSeries::hovered, this, &Plot::slot_tool_tip);
36 | connect_markers();
37 | }
38 |
39 | void LinePlot::delete_line(const QString& name)
40 | {
41 | if (!m_name2series.contains(name))
42 | return;
43 | m_chart->removeSeries(m_name2series[name]);
44 | m_name2series.remove(name);
45 |
46 | m_range[0].pop();
47 | m_range[1].pop();
48 | m_range[2].pop();
49 | m_range[3].pop();
50 |
51 | m_min_x=m_range[0].top();
52 | m_max_x=m_range[1].top();
53 | m_min_y=m_range[2].top();
54 | m_max_y=m_range[3].top();
55 |
56 | m_axisX->setRange(m_min_x , m_max_x );
57 | m_axisY->setRange(m_min_y , m_max_y );
58 | }
59 |
60 | void LinePlot::init_chart()
61 | {
62 | //m_chart->legend()->hide();
63 | }
64 |
65 | void LinePlot::init_axis()
66 | {
67 | m_axisX = new QValueAxis();
68 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
69 |
70 | m_axisY = new QValueAxis();
71 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
72 | }
73 |
74 | void LinePlot::init_series()
75 | {
76 | m_name2series.clear();
77 | }
78 |
79 | void LinePlot::prepare_data(QList& poslist)
80 | {
81 | for (auto& pos : poslist)
82 | {
83 | if (pos.x() < m_min_x)
84 | m_min_x = pos.x();
85 | if (pos.x() > m_max_x)
86 | m_max_x = pos.x();
87 | if (pos.y() < m_min_y)
88 | m_min_y = pos.y();
89 | if (pos.y() > m_max_y)
90 | m_max_y = pos.y();
91 | }
92 | m_range[0].push(m_min_x);
93 | m_range[1].push(m_max_x);
94 | m_range[2].push(m_min_y);
95 | m_range[3].push(m_max_y);
96 | }
97 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/waterfall_plot.h:
--------------------------------------------------------------------------------
1 | #ifndef WATERFALL_PLOT_H
2 | #define WATERFALL_PLOT_H
3 |
4 | #include "plot.h"
5 | #include "graph_global.h"
6 | #include "data.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "graphics_item.h"
12 |
13 | //////////////////////////////////////////////////////////////////////////////
14 | /// 瀑布图
15 | class WaterfallItem :public GraphicsItem
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | WaterfallItem();
21 | void set_chart(QChart* chart);
22 | void set_data(QList data);
23 | void set_series(QBarSet* series);
24 |
25 | signals:
26 | void signal_prepare_path() const;
27 |
28 | public slots:
29 | void slot_prepare_path();
30 |
31 | protected:
32 | QRectF boundingRect() const override;
33 | void on_paint(QPainter* painter) override;
34 |
35 | private:
36 | QChart* m_chart = nullptr;
37 | QList m_data;
38 | QBarSet* m_series = nullptr;
39 | QPainterPath m_shape;
40 | };
41 |
42 | class GRAPH_EXPORT WaterfallPlot : public Plot
43 | {
44 | Q_OBJECT
45 |
46 | public:
47 |
48 | WaterfallPlot(QWidget *parent = nullptr);
49 |
50 | ~WaterfallPlot();
51 |
52 | public:
53 |
54 | void set_data(QList& value_list);
55 |
56 | void clear_data();
57 |
58 | protected:
59 |
60 | virtual void init_chart() override;
61 |
62 | virtual void init_axis() override;
63 |
64 | virtual void init_series() override;
65 |
66 | void init_item();
67 |
68 | private:
69 | /** 名称和系列映射 */
70 | //QMap m_name2itemlist;
71 | /** X 轴 */
72 | QBarCategoryAxis* m_axisX = nullptr;
73 | /** Y 轴 */
74 | QValueAxis* m_axisY = nullptr;
75 | /** Y 轴刻度 */
76 | QStringList m_axis_list;
77 |
78 | QBarSeries* m_bar = nullptr;
79 |
80 | QBarSet* m_bar_start = nullptr;
81 |
82 | QBarSet* m_bar_end = nullptr;
83 |
84 | QBarSet* m_bar_add = nullptr;
85 |
86 | QBarSet* m_bar_low = nullptr;
87 |
88 | WaterfallItem* m_item_start = nullptr;
89 |
90 | WaterfallItem* m_item_end = nullptr;
91 |
92 | WaterfallItem* m_item_add = nullptr;
93 |
94 | WaterfallItem* m_item_low = nullptr;
95 |
96 | /** 起始值 */
97 | double start_value = 0;
98 | };
99 |
100 | #endif // WATERFALL_PLOT_H
--------------------------------------------------------------------------------
/projects/Graph/src/chart/scatter_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "scatter_plot.h"
4 |
5 | ScatterPlot::ScatterPlot(QWidget* parent)
6 | : Plot(parent)
7 | {
8 | init_series();
9 | init_chart();
10 | init_axis();
11 | }
12 |
13 | ScatterPlot::~ScatterPlot()
14 | {
15 |
16 | }
17 |
18 | void ScatterPlot::add_scatter(QList& poslist, const QString& name)
19 | {
20 | if (m_name2series.contains(name))
21 | return;
22 |
23 | prepare_data(poslist);
24 |
25 | QScatterSeries* series = new QScatterSeries();
26 | series->append(poslist);
27 | series->setName(name);
28 | m_chart->addSeries(series);
29 | m_name2series[name] = series;
30 | series->attachAxis(m_axisX);
31 | series->attachAxis(m_axisY);
32 | m_axisX->setRange(m_min_x, m_max_x);
33 | m_axisY->setRange(m_min_y, m_max_y);
34 |
35 | connect(series, &QScatterSeries::hovered, this, &Plot::slot_tool_tip);
36 | connect_markers();
37 | }
38 |
39 | void ScatterPlot::delete_scatter(const QString& name)
40 | {
41 | if (!m_name2series.contains(name))
42 | return;
43 | m_chart->removeSeries(m_name2series[name]);
44 | m_name2series.remove(name);
45 |
46 | m_range[0].pop();
47 | m_range[1].pop();
48 | m_range[2].pop();
49 | m_range[3].pop();
50 |
51 | m_min_x = m_range[0].top();
52 | m_max_x = m_range[1].top();
53 | m_min_y = m_range[2].top();
54 | m_max_y = m_range[3].top();
55 |
56 | m_axisX->setRange(m_min_x, m_max_x);
57 | m_axisY->setRange(m_min_y, m_max_y);
58 | }
59 |
60 | void ScatterPlot::init_chart()
61 | {
62 | //m_chart->legend()->hide();
63 | }
64 |
65 | void ScatterPlot::init_axis()
66 | {
67 | m_axisX = new QValueAxis();
68 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
69 |
70 | m_axisY = new QValueAxis();
71 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
72 | }
73 |
74 | void ScatterPlot::init_series()
75 | {
76 | m_name2series.clear();
77 | }
78 |
79 | void ScatterPlot::prepare_data(QList& poslist)
80 | {
81 | for (auto& pos : poslist)
82 | {
83 | if (pos.x() < m_min_x)
84 | m_min_x = pos.x();
85 | if (pos.x() > m_max_x)
86 | m_max_x = pos.x();
87 | if (pos.y() < m_min_y)
88 | m_min_y = pos.y();
89 | if (pos.y() > m_max_y)
90 | m_max_y = pos.y();
91 | }
92 | m_range[0].push(m_min_x);
93 | m_range[1].push(m_max_x);
94 | m_range[2].push(m_min_y);
95 | m_range[3].push(m_max_y);
96 | }
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | QtChart
2 |
3 | 基于QChart的部分封装二维数据可视化。
4 |
5 | 
6 |
7 | 曲线
8 |
9 | 
10 |
11 | 散点
12 |
13 | 
14 |
15 | 正态概率图
16 |
17 | 
18 |
19 | QQ图
20 |
21 | 
22 |
23 | 帕累托图
24 |
25 | 
26 |
27 | 饼图
28 |
29 | 
30 |
31 | 股票图
32 |
33 | 
34 |
35 | 柱状图
36 |
37 | 
38 |
39 | 表格
40 |
41 | 
42 |
43 | 径向图
44 |
45 | 
46 |
47 | 统计条形图
48 |
49 | 
50 |
51 | 自定义绘制
52 |
53 | 
54 |
55 | 彩色点图(计算效率需要优化)
56 |
57 | 
58 |
59 | 密度点图(计算效率需要优化)
60 |
61 | 
62 |
63 | 雷达图
64 |
65 | 
66 |
67 | 直方图
68 |
69 | 
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/color_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "color_plot.h"
4 | #include "color_bar.h"
5 |
6 | ColorPlot::ColorPlot(QWidget *parent)
7 | : Plot(parent)
8 | {
9 | init_series();
10 | init_chart();
11 | init_axis();
12 | }
13 |
14 | ColorPlot::~ColorPlot()
15 | {
16 |
17 | }
18 |
19 | void ColorPlot::set_data(QList& value_list)
20 | {
21 | for (auto& item : value_list)
22 | {
23 | if (m_min_x > item.m_x)
24 | m_min_x = item.m_x;
25 | if (m_max_x < item.m_x)
26 | m_max_x = item.m_x;
27 | if (m_min_y > item.m_y)
28 | m_min_y = item.m_y;
29 | if (m_max_y < item.m_y)
30 | m_max_y = item.m_y;
31 | if (m_min_z > item.m_z)
32 | m_min_z = item.m_z;
33 | if (m_max_z < item.m_z)
34 | m_max_z = item.m_z;
35 |
36 | if (value2series.contains(item.m_z))
37 | value2series[item.m_z]->append(QPointF(item.m_x, item.m_y));
38 | else
39 | {
40 | QScatterSeries* scatter = new QScatterSeries; //散点图
41 | scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
42 | scatter->setMarkerSize(3.0);
43 | scatter->setBorderColor(Qt::transparent);
44 | scatter->append(QPointF(item.m_x, item.m_y));
45 | value2series[item.m_z] = scatter;
46 | }
47 | }
48 |
49 | m_axisX->setRange(m_min_x, m_max_x);
50 | m_axisY->setRange(m_min_y, m_max_y);
51 | m_color_item->set_value_range(m_min_z, m_max_z);
52 |
53 | for (auto it = value2series.begin(); it != value2series.end(); ++it)
54 | {
55 | m_chart->addSeries(it.value());
56 | it.value()->attachAxis(m_axisX);
57 | it.value()->attachAxis(m_axisY);
58 | it.value()->setBrush(m_color_item->getColor(it.key()));
59 | it.value()->setUseOpenGL(true);
60 | }
61 | }
62 |
63 | void ColorPlot::clear_data()
64 | {
65 | value2series.clear();
66 | m_chart->series().clear();
67 | }
68 |
69 | void ColorPlot::init_chart()
70 | {
71 | m_chart->legend()->hide();
72 |
73 | m_color_item = new ColorBar();
74 | m_color_item->set_chart(m_chart);
75 | m_chartview->add_item(m_color_item);
76 | }
77 |
78 | void ColorPlot::init_axis()
79 | {
80 | m_axisX = new QValueAxis();
81 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
82 | m_axisX->setGridLineVisible(false);
83 |
84 | m_axisY = new QValueAxis();
85 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
86 | m_axisY->setGridLineVisible(false);
87 | }
88 |
89 | void ColorPlot::init_series()
90 | {
91 | value2series.clear();
92 | }
93 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph/chart_view_preview.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "chart_view_preview.h"
4 | #include "util.h"
5 | #include "chart_view.h"
6 |
7 | #include
8 | #include
9 |
10 | QMap ChartViewPreview::s_view2preview;
11 |
12 | ChartViewPreview::~ChartViewPreview()
13 | {
14 | //清理全局预览对象
15 | s_view2preview.remove(m_view);
16 | //恢复鼠标形状
17 | m_view->set_cursor_auto();
18 | }
19 |
20 | bool ChartViewPreview::is_previewing(ChartView* view)
21 | {
22 | return s_view2preview.contains(view);
23 | }
24 |
25 | void ChartViewPreview::finish_all(ChartView* view)
26 | {
27 | auto preview = s_view2preview.take(view);
28 | if (preview != nullptr)
29 | {
30 | preview->finish_preview();
31 | delete preview;
32 | }
33 | }
34 |
35 | void ChartViewPreview::begin_preview(ChartView* view)
36 | {
37 | m_view = view;
38 |
39 | //一个视图窗口只能有一个预览
40 | finish_all(m_view);
41 |
42 | //记录预览图元
43 | s_view2preview[m_view] = this;
44 |
45 | //显示cad光标
46 | m_view->set_cursor_auto();
47 |
48 | set_step(BEGIN_PREVIEW);
49 | }
50 |
51 | void ChartViewPreview::finish_preview()
52 | {
53 | set_step(BEGIN_PREVIEW);
54 | on_finish_preview();
55 | }
56 |
57 | void ChartViewPreview::advance_preview(const QPoint& point)
58 | {
59 | QPointF pos = m_view->map_to_scene(point);
60 | on_advance_preview(pos);
61 | }
62 |
63 | void ChartViewPreview::on_mouse_move(ChartView* view, QMouseEvent* event)
64 | {
65 | if (s_view2preview.contains(view))
66 | {
67 | s_view2preview[view]->on_mouse_move(event);
68 | }
69 | }
70 |
71 | void ChartViewPreview::on_mouse_move(QMouseEvent* event)
72 | {
73 | QPointF pos = m_view->map_to_scene(event->pos());
74 | on_mouse_move(pos);
75 | m_view->redraw();
76 | }
77 |
78 | void ChartViewPreview::set_step(int step)
79 | {
80 | m_step = step;
81 | }
82 |
83 | void ChartViewPreview::on_mouse_release(ChartView* view, QMouseEvent* event)
84 | {
85 | if (!s_view2preview.contains(view)) return;
86 |
87 | auto preview = s_view2preview[view];
88 |
89 | if (event->button() == Qt::LeftButton)
90 | {
91 | preview->advance_preview(event->pos());
92 | }
93 | else if (event->button() == Qt::RightButton)
94 | {
95 | if (preview->step() == BEGIN_PREVIEW)
96 | delete preview;
97 | else preview->finish_preview();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/table.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "table.h"
4 |
5 | Table::Table(QWidget *parent)
6 | : QWidget(parent)
7 | {
8 | m_table = new QTableWidget();
9 | m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
10 |
11 | QHBoxLayout* layout = new QHBoxLayout;
12 | layout->setMargin(0);
13 | layout->setSpacing(0);
14 | layout->addWidget(m_table);
15 | setLayout(layout);
16 | }
17 |
18 | Table::~Table()
19 | {
20 |
21 | }
22 |
23 | void Table::add_data(QList& list, const QString& name)
24 | {
25 | m_head_list.append(name);
26 | m_table->setColumnCount(m_head_list.size());
27 | m_table->setHorizontalHeaderLabels(m_head_list);
28 | for (int i = 0; i < list.size(); i++)
29 | {
30 | int count = m_table->rowCount();
31 | if (i < count)
32 | m_table->setItem(i, m_head_list.size()-1,new QTableWidgetItem(QString::number(list[i])));
33 | else
34 | {
35 | m_table->setRowCount(count + 1);
36 | m_table->setItem(count, m_head_list.size() - 1, new QTableWidgetItem(QString::number(list[i])));
37 | }
38 | }
39 | }
40 |
41 | void Table::add_data(QList& list, const QString& name)
42 | {
43 | m_head_list.append(name);
44 | m_table->setColumnCount(m_head_list.size());
45 | m_table->setHorizontalHeaderLabels(m_head_list);
46 | for (int i = 0; i < list.size(); i++)
47 | {
48 | int count = m_table->rowCount();
49 | if (i < count)
50 | m_table->setItem(i, m_head_list.size() - 1, new QTableWidgetItem(QString::number(list[i])));
51 | else
52 | {
53 | m_table->setRowCount(count + 1);
54 | m_table->setItem(count, m_head_list.size() - 1, new QTableWidgetItem(QString::number(list[i])));
55 | }
56 | }
57 | }
58 |
59 | void Table::add_data(QList& list, const QString& name)
60 | {
61 | m_head_list.append(name);
62 | m_table->setColumnCount(m_head_list.size());
63 | m_table->setHorizontalHeaderLabels(m_head_list);
64 | for (int i = 0; i < list.size(); i++)
65 | {
66 | int count = m_table->rowCount();
67 | if (i < count)
68 | m_table->setItem(i, m_head_list.size() - 1, new QTableWidgetItem(list[i]));
69 | else
70 | {
71 | m_table->setRowCount(count + 1);
72 | m_table->setItem(count, m_head_list.size() - 1, new QTableWidgetItem(list[i]));
73 | }
74 | }
75 | }
76 |
77 | void Table::delete_data(const QString& name)
78 | {
79 | m_head_list.removeOne(name);
80 | m_table->setColumnCount(m_head_list.size());
81 | m_table->setHorizontalHeaderLabels(m_head_list);
82 | }
83 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/density_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "density_plot.h"
4 | #include "color_bar.h"
5 |
6 | DensityPlot::DensityPlot(QWidget *parent)
7 | : Plot(parent)
8 | {
9 | init_series();
10 | init_chart();
11 | init_axis();
12 | }
13 |
14 | DensityPlot::~DensityPlot()
15 | {
16 |
17 | }
18 |
19 | void DensityPlot::set_data(QList& pos_list)
20 | {
21 | QVector dataset;
22 |
23 | for (auto& item : pos_list)
24 | {
25 | if (m_min_x > item.x())
26 | m_min_x = item.x();
27 | if (m_max_x < item.x())
28 | m_max_x = item.x();
29 | if (m_min_y > item.y())
30 | m_min_y = item.y();
31 | if (m_max_y < item.y())
32 | m_max_y = item.y();
33 |
34 | dataset.push_back(DensityPoint(item.x(), item.y()));
35 | }
36 |
37 | calculateDensity(dataset, radius);
38 |
39 | for (int i = 0; i < dataset.size(); i++)
40 | {
41 | auto pos = dataset.at(i);
42 | int zi = pos.pts;
43 | qreal x = pos.x;
44 | qreal y = pos.y;
45 | if (value2series.contains(zi))
46 | value2series[zi]->append(x, y);
47 | else
48 | {
49 | QScatterSeries* scatter = new QScatterSeries; //散点图
50 | //scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
51 | scatter->setMarkerSize(3.0);
52 | scatter->setBorderColor(Qt::transparent);
53 | scatter->append(x, y);
54 | value2series[zi] = scatter;
55 | }
56 | }
57 |
58 | m_axisX->setRange(m_min_x, m_max_x);
59 | m_axisY->setRange(m_min_y, m_max_y);
60 | m_color_item->set_value_range(1.0, value2series.size());
61 |
62 | for (auto it = value2series.begin(); it != value2series.end(); ++it)
63 | {
64 | m_chart->addSeries(it.value());
65 | it.value()->attachAxis(m_axisX);
66 | it.value()->attachAxis(m_axisY);
67 | it.value()->setBrush(m_color_item->getColor(it.key()));
68 | it.value()->setUseOpenGL(true);
69 | }
70 | }
71 |
72 | void DensityPlot::clear_data()
73 | {
74 | value2series.clear();
75 | m_chart->series().clear();
76 | }
77 |
78 | void DensityPlot::init_chart()
79 | {
80 | m_chart->legend()->hide();
81 |
82 | m_color_item = new ColorBar();
83 | m_color_item->set_chart(m_chart);
84 | m_chartview->add_item(m_color_item);
85 | }
86 |
87 | void DensityPlot::init_axis()
88 | {
89 | m_axisX = new QValueAxis();
90 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
91 | m_axisX->setGridLineVisible(false);
92 |
93 | m_axisY = new QValueAxis();
94 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
95 | m_axisY->setGridLineVisible(false);
96 | }
97 |
98 | void DensityPlot::init_series()
99 | {
100 | value2series.clear();
101 | }
102 |
103 | double DensityPlot::squareDistance(DensityPoint a, DensityPoint b)
104 | {
105 | return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
106 | }
107 |
108 | void DensityPlot::calculateDensity(QVector& dataset, float Eps)
109 | {
110 | int len = dataset.size();
111 |
112 | for (int i = 0; i < len; i++)
113 | {
114 | for (int j = i + 1; j < len; j++)
115 | {
116 | if (squareDistance(dataset[i], dataset[j]) <= Eps)
117 | {
118 | dataset[i].pts++;
119 | dataset[j].pts++;
120 | }
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/pareto_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "pareto_plot.h"
4 | #include
5 | using namespace std;
6 |
7 | ParetoPlot::ParetoPlot(QWidget *parent)
8 | : Plot(parent)
9 | {
10 | init_series();
11 | init_chart();
12 | init_axis();
13 | }
14 |
15 | ParetoPlot::~ParetoPlot()
16 | {
17 |
18 | }
19 |
20 | void ParetoPlot::set_data(QList& value_list)
21 | {
22 | QList data = prepare_data(value_list);
23 |
24 | QVector line_center_poslist;
25 | QVector scatter_poslist;
26 |
27 | for (int i = 0; i < data.size(); i++)
28 | {
29 | m_axisy_list.append(data[i].m_name);
30 | m_set->append(data[i].m_value);
31 |
32 | line_center_poslist.append(QPointF(i, data[i].m_percent));
33 | scatter_poslist.append(QPointF(i, data[i].m_percent));
34 | }
35 |
36 | m_line->replace(line_center_poslist);
37 | m_scatter->replace(scatter_poslist);
38 |
39 | m_axisY_1->setRange(1, 60);
40 | m_axisX->append(m_axisy_list);
41 | m_axisX->setRange(m_axisy_list.first(), m_axisy_list.last());
42 |
43 | //connect(m_scatter, &QScatterSeries::hovered, this, &Plot::slot_tool_tip);
44 | }
45 |
46 | void ParetoPlot::clear_data()
47 | {
48 | m_line->clear();
49 | m_scatter->clear();
50 | m_bar->clear();
51 | }
52 |
53 | void ParetoPlot::init_chart()
54 | {
55 | m_chart->legend()->hide();
56 | m_chart->addSeries(m_bar);
57 | m_chart->addSeries(m_line);
58 | m_chart->addSeries(m_scatter);
59 | }
60 |
61 | void ParetoPlot::init_axis()
62 | {
63 | m_axisX = new QBarCategoryAxis();
64 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
65 | m_line->attachAxis(m_axisX);
66 | m_bar->attachAxis(m_axisX);
67 | m_scatter->attachAxis(m_axisX);
68 |
69 | m_axisY_1 = new QValueAxis();
70 | m_axisY_1->setTitleText("计数");
71 | m_chart->addAxis(m_axisY_1, Qt::AlignLeft);
72 | m_bar->attachAxis(m_axisY_1);
73 |
74 | m_axisY_2 = new QValueAxis();
75 | m_axisY_2->setTitleText("累积频率");
76 | m_axisY_2->setTickCount(12);
77 | m_axisY_2->setRange(0, 110);
78 | m_axisY_2->setLabelFormat("%.1f%");
79 | m_axisY_2->setGridLineVisible(false); //隐藏背景网格Y轴框线
80 | m_chart->addAxis(m_axisY_2, Qt::AlignRight);
81 | m_line->attachAxis(m_axisY_2);
82 | m_scatter->attachAxis(m_axisY_2);
83 | }
84 |
85 | void ParetoPlot::init_series()
86 | {
87 | m_set = new QBarSet("");
88 | m_bar = new QBarSeries();
89 | m_bar->append(m_set);
90 |
91 | m_line = new QLineSeries();
92 | m_line->append(QPointF(0, 0));
93 |
94 | m_scatter = new QScatterSeries();
95 | m_scatter->append(QPointF(0, 0));
96 | m_scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
97 | m_scatter->setMarkerSize(10);
98 | m_scatter->setPointLabelsVisible();
99 | m_scatter->setPointLabelsFormat("@yPoint%");
100 | m_scatter->setPointLabelsClipping(false);
101 | }
102 |
103 | QList& ParetoPlot::prepare_data(QList& value_list)
104 | {
105 | qSort(value_list.begin(), value_list.end(),
106 | [](const ParetoData& data1,const ParetoData& data2)
107 | {
108 | return data1.m_value > data2.m_value;
109 | });
110 | double sum = accumulate(value_list.begin(), value_list.end(), 0,
111 | [](double a, ParetoData b)
112 | {
113 | return a + b.m_value;
114 | });
115 | double result = 0;
116 | for (auto& item :value_list)
117 | {
118 | result += item.m_value;
119 | item.m_percent = result / sum * 100;
120 | }
121 | return value_list;
122 | }
123 |
124 |
125 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/SizeGripItem.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SizeGripItem - A size grip QGraphicsItem for interactive resizing.
3 | *
4 | * Copyright (c) 2011 Cesar L. B. Silveira
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a
7 | * copy of this software and associated documentation files (the "Software"),
8 | * to deal in the Software without restriction, including without limitation
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | * and/or sell copies of the Software, and to permit persons to whom the
11 | * Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included
14 | * in all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 | * IN THE SOFTWARE.
23 | */
24 |
25 | #ifndef SIZEGRIPITEM_H
26 | #define SIZEGRIPITEM_H
27 |
28 | #include
29 | #include
30 |
31 | class SizeGripItem : public QGraphicsItem
32 | {
33 | private:
34 | enum
35 | {
36 | Top = 0x1,
37 | Bottom = 0x2,
38 | Left = 0x4,
39 | TopLeft = Top | Left,
40 | BottomLeft = Bottom | Left,
41 | Right = 0x8,
42 | TopRight = Top | Right,
43 | BottomRight = Bottom | Right
44 | };
45 |
46 | class HandleItem : public QGraphicsRectItem
47 | {
48 | public:
49 | HandleItem(int positionFlags, SizeGripItem* parent);
50 | int positionFlags() const;
51 |
52 | protected:
53 | virtual QVariant itemChange(GraphicsItemChange change,
54 | const QVariant &value);
55 |
56 | private:
57 | QPointF restrictPosition(const QPointF& newPos);
58 |
59 | int positionFlags_;
60 | SizeGripItem* parent_;
61 | };
62 |
63 | public:
64 | class Resizer
65 | {
66 | public:
67 | virtual void operator()(QGraphicsItem* item,
68 | const QRectF& rect) = 0;
69 | };
70 |
71 | SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0);
72 | virtual ~SizeGripItem();
73 | virtual QRectF boundingRect() const;
74 | virtual void paint(QPainter* painter,
75 | const QStyleOptionGraphicsItem* option,
76 | QWidget* widget = 0);
77 | void setTopLeft(const QPointF& pos);
78 | void setTop(qreal y);
79 | void setTopRight(const QPointF& pos);
80 | void setRight(qreal x);
81 | void setBottomRight(const QPointF& pos);
82 | void setBottom(qreal y);
83 | void setBottomLeft(const QPointF& pos);
84 | void setLeft(qreal x);
85 |
86 | private:
87 | void doResize();
88 | void updateHandleItemPositions();
89 |
90 | QList handleItems_;
91 | QRectF rect_;
92 | Resizer* resizer_;
93 | };
94 |
95 | #endif // SIZEGRIPITEM_H
96 |
--------------------------------------------------------------------------------
/projects/Graph/src/graph/poly_line.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "poly_line.h"
4 | #include "util.h"
5 | #include
6 | #include
7 |
8 | PolyLine::PolyLine()
9 | : GraphicsItem()
10 | {
11 | setZValue(1);
12 | setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
13 | }
14 |
15 | QList PolyLine::get_points() const
16 | {
17 | return m_points;
18 | }
19 |
20 | void PolyLine::set_points(const QList& points)
21 | {
22 | m_points = points;
23 | }
24 |
25 | void PolyLine::append_point(const QPointF& point)
26 | {
27 | m_points.append(point);
28 | }
29 |
30 | QPointF PolyLine::get_last_point() const
31 | {
32 | QPointF lpt;
33 | if (!m_points.isEmpty())
34 | lpt = m_points.last();
35 | return lpt;
36 | }
37 |
38 | void PolyLine::set_last_point(const QPointF& point)
39 | {
40 | m_points.pop_back();
41 | append_point(point);
42 | }
43 |
44 | QRectF PolyLine::boundingRect() const
45 | {
46 | auto points = get_points();
47 | for (auto& p : points) p.setY(-p.y());
48 | QRectF rect = Util::bounding_rect(points);
49 | return rect;
50 | }
51 |
52 | void PolyLine::on_paint(QPainter* painter)
53 | {
54 | auto points = get_points().toVector();
55 | for (int i = 0; i < points.size() - 1; ++i)
56 | {
57 | auto p1 = points[i];
58 | auto p2 = points[i + 1];
59 | if ((p1 - p2).manhattanLength() > TOLERANCE)
60 | {
61 | p1.setY(-p1.y());
62 | p2.setY(-p2.y());
63 | painter->drawLine(p1, p2);
64 | }
65 | }
66 | }
67 |
68 | GraphicsItem* PolyLine::clone()
69 | {
70 | PolyLine* line = new PolyLine();
71 | line->set_points(m_points);
72 | return line;
73 | }
74 |
75 | ///////////////////////////////////////////////////////////////////////////////
76 | //箭头线
77 | Arrows::Arrows()
78 | {
79 |
80 | }
81 |
82 | GraphicsItem* Arrows::clone()
83 | {
84 | Arrows* arrows = new Arrows();
85 | arrows->set_points(m_points);
86 | return arrows;
87 | }
88 |
89 | void Arrows::on_paint(QPainter* painter)
90 | {
91 | auto points = get_points().toVector();
92 | for (int i = 0; i < points.size() - 1; ++i)
93 | {
94 | auto p1 = points[i];
95 | auto p2 = points[i + 1];
96 | if ((p1 - p2).manhattanLength() > TOLERANCE)
97 | {
98 | p1.setY(-p1.y());
99 | p2.setY(-p2.y());
100 | painter->drawLine(p1, p2);
101 |
102 | if (i + 1 == points.size() - 1)
103 | {
104 | QLineF line(p1, p2);
105 | double angle = std::atan2(-line.dy(), line.dx());
106 | qreal arrowSize = 10;
107 | QPointF arrowP1 = line.p2() - QPointF(sin(angle + PI / 3) * arrowSize,
108 | cos(angle + PI / 3) * arrowSize);
109 | QPointF arrowP2 = line.p2() - QPointF(sin(angle + PI - PI / 3) * arrowSize,
110 | cos(angle + PI - PI / 3) * arrowSize);
111 | QPolygonF arrowHead;
112 | arrowHead << line.p2() << arrowP2 << arrowP1;
113 | painter->drawLine(p2, arrowP1);
114 | painter->drawLine(p2, arrowP2);
115 | }
116 | }
117 | else
118 | {
119 | auto p1 = points[i - 1]; p1.setY(-p1.y());
120 | auto p2 = points[i]; p2.setY(-p2.y());
121 | QLineF line(p1, p2);
122 | double angle = std::atan2(-line.dy(), line.dx());
123 | qreal arrowSize = 10;
124 | QPointF arrowP1 = line.p2() - QPointF(sin(angle + PI / 3) * arrowSize,
125 | cos(angle + PI / 3) * arrowSize);
126 | QPointF arrowP2 = line.p2() - QPointF(sin(angle + PI - PI / 3) * arrowSize,
127 | cos(angle + PI - PI / 3) * arrowSize);
128 | QPolygonF arrowHead;
129 | arrowHead << line.p2() << arrowP2 << arrowP1;
130 | painter->drawLine(p2, arrowP1);
131 | painter->drawLine(p2, arrowP2);
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "plot.h"
4 | #include "tool_tip.h"
5 | #include "chart_view.h"
6 | #include "poly_line_preview.h"
7 |
8 | Plot::Plot(bool IsPolar, QWidget *parent)
9 | : QWidget(parent)
10 | {
11 | if (IsPolar)
12 | m_chart = new QPolarChart();
13 | else
14 | m_chart = new QChart();
15 | m_chartview = new ChartView(m_chart);
16 |
17 | QHBoxLayout* layout = new QHBoxLayout;
18 | layout->setMargin(0);
19 | layout->setSpacing(0);
20 | layout->addWidget(m_chartview);
21 | setLayout(layout);
22 | }
23 |
24 | Plot::~Plot()
25 | {
26 | }
27 |
28 | void Plot::slot_tool_tip(QPointF point, bool state)
29 | {
30 | if (m_tooltip == nullptr)
31 | m_tooltip = new ToolTip(m_chart);
32 | if (state) {
33 | m_tooltip->setText(QString("X: %1 \nY: %2 ").arg(point.x()).arg(point.y()));
34 | m_tooltip->setAnchor(point);
35 | m_tooltip->setZValue(11);
36 | m_tooltip->updateGeometry();
37 | m_tooltip->show();
38 | }
39 | else
40 | m_tooltip->hide();
41 | }
42 |
43 | void Plot::add_title(const QString& name)
44 | {
45 | m_chart->setTitle(name);
46 | }
47 |
48 | void Plot::connect_markers()
49 | {
50 | const auto markers = m_chart-> legend()->markers();
51 | for (QLegendMarker* marker : markers)
52 | {
53 | disconnect(marker, &QLegendMarker::clicked, this, &Plot::slot_handle_marker_clicked);
54 | connect(marker, &QLegendMarker::clicked, this, &Plot::slot_handle_marker_clicked);
55 | }
56 | }
57 |
58 | void Plot::disconnect_markers()
59 | {
60 | const auto markers = m_chart->legend()->markers();
61 | for (QLegendMarker* marker : markers)
62 | disconnect(marker, &QLegendMarker::clicked, this, &Plot::slot_handle_marker_clicked);
63 | }
64 |
65 | void Plot::draw_line()
66 | {
67 | new PolyLinePreview(m_chartview);
68 | }
69 |
70 | void Plot::draw_arrows()
71 | {
72 | new ArrowsPreview(m_chartview);
73 | }
74 |
75 | void Plot::resizeEvent(QResizeEvent* event)
76 | {
77 | //遍历每一个图例
78 | //const auto markers = m_chart->legend()->markers();
79 | //for (QLegendMarker* marker : markers)
80 | //{
81 | // if (marker = markers[1])
82 | // marker->setVisible(false);
83 | //}
84 |
85 | //QLegend* legend = m_chart->legend();
86 | //if (legend->isAttachedToChart()) {
87 | // legend->detachFromChart();
88 | // m_chart->legend()->setGeometry(m_chart->plotArea().x(), m_chart->plotArea().y(), 100, 100);
89 | // m_chart->legend()->setBackgroundVisible(true);
90 | // m_chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
91 | // m_chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
92 | // m_chart->legend()->update();
93 | //}
94 | }
95 |
96 | void Plot::slot_handle_marker_clicked()
97 | {
98 | QLegendMarker* marker = qobject_cast (sender());
99 | Q_ASSERT(marker);
100 |
101 | switch (marker->type())
102 | {
103 | case QLegendMarker::LegendMarkerTypeXY:
104 | {
105 | marker->series()->setVisible(!marker->series()->isVisible());
106 | marker->setVisible(true);
107 | qreal alpha = 1.0;
108 |
109 | if (!marker->series()->isVisible())
110 | alpha = 0.5;
111 |
112 | QColor color;
113 | QBrush brush = marker->labelBrush();
114 | color = brush.color();
115 | color.setAlphaF(alpha);
116 | brush.setColor(color);
117 | marker->setLabelBrush(brush);
118 |
119 | brush = marker->brush();
120 | color = brush.color();
121 | color.setAlphaF(alpha);
122 | brush.setColor(color);
123 | marker->setBrush(brush);
124 |
125 | QPen pen = marker->pen();
126 | color = pen.color();
127 | color.setAlphaF(alpha);
128 | pen.setColor(color);
129 | marker->setPen(pen);
130 | break;
131 | }
132 | default:
133 | break;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/interval_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "interval_plot.h"
4 | #include "chart_view.h"
5 | #include "util.h"
6 | #include "color_bar.h"
7 |
8 | IntervalPlot::IntervalPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | }
15 |
16 | IntervalPlot::~IntervalPlot()
17 | {
18 |
19 | }
20 |
21 | void IntervalPlot::set_data(QList& list)
22 | {
23 | for (int i = 0; i < list.size(); i++)
24 | {
25 | double min, max;
26 | add_interval(list[i], i, min, max);
27 | m_axisx_list.append(list[i].m_name);
28 | if (max > m_max_y)
29 | m_max_y = max;
30 | if (min < m_min_y)
31 | m_min_y = min;
32 | }
33 | m_axisX->setCategories(m_axisx_list);
34 | m_axisY->setRange(m_min_y * 0.9, m_max_y * 1.1);
35 | }
36 |
37 | void IntervalPlot::add_interval(BoxData& data, int index, double& y_min, double& y_max)
38 | {
39 | if (m_name2item.contains(data.m_name))
40 | return;
41 |
42 | IntervalItem* item = new IntervalItem();
43 | item->set_data(data, index);
44 | item->set_chart(m_chart);
45 | y_min = item->get_min();
46 | y_max = item->get_max();
47 | m_chartview->add_item(item);
48 | m_name2item[data.m_name] = item;
49 | }
50 |
51 | void IntervalPlot::init_chart()
52 | {
53 | //m_chart->legend()->hide();
54 | m_chart->addSeries(m_series);
55 | }
56 |
57 | void IntervalPlot::init_axis()
58 | {
59 | m_axisX = new QBarCategoryAxis();
60 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
61 | m_series->attachAxis(m_axisX);
62 |
63 | m_axisY = new QValueAxis();
64 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
65 | m_series->attachAxis(m_axisY);
66 | }
67 |
68 | void IntervalPlot::init_series()
69 | {
70 | m_series = new QScatterSeries();
71 | }
72 |
73 | //////////////////////////////////////////////////////////////////////////////
74 | /// 间隔图
75 | IntervalItem::IntervalItem()
76 | {
77 | connect(this, &IntervalItem::signal_prepare_path, this, &IntervalItem::slot_prepare_path);
78 | }
79 |
80 | void IntervalItem::set_chart(QChart* chart)
81 | {
82 | m_chart = chart;
83 | }
84 |
85 | void IntervalItem::set_data(BoxData& data, int index)
86 | {
87 | double mean, sum, min, max;
88 | Util::cal_list(data.m_value_list, mean, sum, max, min);
89 |
90 | m_list = data.m_value_list;
91 | m_name = data.m_name;
92 | m_min = QPointF(index, min);
93 | m_max = QPointF(index, max);
94 | m_mean = QPointF(index, mean);
95 | m_sum = QPointF(index, sum);
96 | }
97 |
98 | double IntervalItem::get_max()
99 | {
100 | return m_max.y();
101 | }
102 |
103 | double IntervalItem::get_min()
104 | {
105 | return m_min.y();
106 | }
107 |
108 | void IntervalItem::slot_prepare_path()
109 | {
110 | QLineF line(m_chart->mapToPosition(QPointF(0, 0)), m_chart->mapToPosition(QPointF(1, 0)));
111 | double width = line.length();
112 | QPointF top = m_chart->mapToPosition(m_max);
113 | QPointF buttom = m_chart->mapToPosition(m_min);
114 | QPointF center = m_chart->mapToPosition(m_mean);
115 | QPointF tl = top - QPointF(width * 0.05, 0);
116 | QPointF tr = top + QPointF(width * 0.05, 0);
117 | QPointF bl = buttom - QPointF(width * 0.05, 0);
118 | QPointF br = buttom + QPointF(width * 0.05, 0);
119 |
120 | QPainterPath path;
121 | path.moveTo(top);
122 | path.lineTo(buttom);
123 | path.moveTo(tl);
124 | path.lineTo(tr);
125 | path.moveTo(bl);
126 | path.lineTo(br);
127 | path.addEllipse(center, width * 0.05, width * 0.05);
128 |
129 | m_shape = path;
130 | }
131 |
132 | QRectF IntervalItem::boundingRect() const
133 | {
134 | emit signal_prepare_path();
135 | return m_chart->plotArea().intersected(m_shape.boundingRect());
136 | }
137 |
138 | void IntervalItem::on_paint(QPainter* painter)
139 | {
140 | painter->setClipRect(boundingRect());
141 | painter->drawPath(m_shape);
142 | }
143 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/radar_plot.cpp:
--------------------------------------------------------------------------------
1 | #include "radar_plot.h"
2 | #include
3 | #include "chart_view.h"
4 | #include "math_define.h"
5 |
6 | RadarPlot::RadarPlot(QWidget *parent)
7 | : Plot(true, parent)
8 | {
9 | init_series();
10 | init_chart();
11 | init_axis();
12 | set_radar_type(m_radartype);
13 | }
14 |
15 | RadarPlot::~RadarPlot()
16 | {
17 | }
18 |
19 | void RadarPlot::set_radar(QStringList& lablelist)
20 | {
21 | count = lablelist.size();
22 | const auto offset = 360 / count;
23 | for (int i = 0; i < count; i++)
24 | m_angularAxis->append(lablelist[i], offset * i);
25 | }
26 |
27 | void RadarPlot::add_radar(QList& valuelist, const QString& name)
28 | {
29 | if (valuelist.size() != count)
30 | return;
31 | if (m_name2series.contains(name))
32 | return;
33 | QLineSeries* series = new QLineSeries();
34 | series->setName(name);
35 | for (int i = 0; i < count; i++)
36 | {
37 | if (valuelist[i] < m_min_x)
38 | m_min_x = valuelist[i];
39 | if (valuelist[i] > m_max_x)
40 | m_max_x = valuelist[i];
41 | series->append(360 / count * i, valuelist[i]);
42 | }
43 | series->append(360, valuelist.first());
44 |
45 | m_chart->addSeries(series);
46 | m_name2series[name] = series;
47 | series->attachAxis(m_angularAxis);
48 | series->attachAxis(m_radialAxis);
49 | m_radialAxis->setRange(m_min_x * 0.9, m_max_x * 1.1);
50 | }
51 |
52 | void RadarPlot::delete_radar(const QString& name)
53 | {
54 | if (!m_name2series.contains(name))
55 | return;
56 | m_chart->removeSeries(m_name2series[name]);
57 | m_name2series.remove(name);
58 | }
59 |
60 | void RadarPlot::set_radar_type(RadarType type)
61 | {
62 | m_radartype = type;
63 | switch (m_radartype)
64 | {
65 | case Radar:
66 | m_radialAxis->setGridLineVisible(true);
67 | m_angularAxis->setLineVisible(true);
68 | item->setVisible(false);
69 | break;
70 | case Spider:
71 | m_radialAxis->setGridLineVisible(false);
72 | m_angularAxis->setLineVisible(false);
73 | item->setVisible(true);
74 | break;
75 | default:
76 | break;
77 | }
78 | }
79 |
80 | void RadarPlot::init_chart()
81 | {
82 | //m_chart->legend()->setVisible(true);
83 | m_chart->legend()->setAlignment(Qt::AlignRight);
84 | item = new RadarItem();
85 | item->set_chart(m_chart);
86 | m_chartview->add_item(item);
87 | }
88 |
89 | void RadarPlot::init_axis()
90 | {
91 | m_angularAxis = new QCategoryAxis();
92 | m_angularAxis->setRange(0, 360);
93 | m_angularAxis->setStartValue(0);
94 | m_angularAxis->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);
95 | dynamic_cast(m_chart)->addAxis(m_angularAxis, QPolarChart::PolarOrientationAngular);
96 |
97 | m_radialAxis = new QValueAxis();
98 | m_radialAxis->setTickCount(7);
99 | dynamic_cast(m_chart)->addAxis(m_radialAxis, QPolarChart::PolarOrientationRadial);
100 | }
101 |
102 | void RadarPlot::init_series()
103 | {
104 | m_name2series.clear();
105 | }
106 |
107 | //////////////////////////////////////////////////////////////////////////////
108 | /// 雷达图
109 | RadarItem::RadarItem()
110 | {
111 |
112 | }
113 |
114 | void RadarItem::set_chart(QChart* chart)
115 | {
116 | m_chart = chart;
117 | }
118 |
119 | void RadarItem::set_radial(int radial)
120 | {
121 | m_radial = radial;
122 | }
123 |
124 | void RadarItem::set_angular(int angular)
125 | {
126 | m_angular = angular;
127 | }
128 |
129 | QRectF RadarItem::boundingRect() const
130 | {
131 | return m_chart->plotArea();
132 | }
133 |
134 | void RadarItem::on_paint(QPainter* painter)
135 | {
136 | for (int i = 0; i <= m_radial; i++)
137 | {
138 | int rad = i * boundingRect().width() / 2 / m_radial ;
139 | QPolygonF poslist;
140 | for (int j = 0; j < m_angular; j++)
141 | {
142 | QPen pen;
143 | QColor color(Qt::lightGray);
144 | pen.setWidthF(0.4);
145 | painter->setPen(pen);
146 | int x = 360 * j / m_angular;
147 | QPointF pos = boundingRect().center() - QPointF(sin(x * PI / 180) * rad, cos(x * PI / 180) * rad);
148 | poslist.append(pos);
149 | }
150 | painter->drawPolygon(poslist);
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/boxbar_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "boxbar_plot.h"
4 | #include "util.h"
5 | #include
6 | #include "chart_view.h"
7 | #include "plot.h"
8 |
9 | BoxBarPlot::BoxBarPlot(QWidget* parent)
10 | : Plot(parent)
11 | {
12 | init_series();
13 | init_chart();
14 | init_axis();
15 | }
16 |
17 | BoxBarPlot::~BoxBarPlot()
18 | {
19 | }
20 |
21 | void BoxBarPlot::set_type(BoxBarType type)
22 | {
23 | switch (type)
24 | {
25 | case MEAN:
26 | break;
27 | case SUM:
28 | break;
29 | case MAX:
30 | break;
31 | case MIN:
32 | break;
33 | default:
34 | break;
35 | }
36 | }
37 |
38 | void BoxBarPlot::set_data(QList& list)
39 | {
40 | for (int i = 0; i < list.size(); i++)
41 | {
42 | if (Util::max(list[i].m_value_list) > m_max_y)
43 | m_max_y = Util::max(list[i].m_value_list);
44 | add_boxbar(list[i],list.size(),i);
45 | }
46 |
47 | m_axisX->setCategories(m_axisx_list);
48 | m_axisY->setRange(0, m_max_y * 1.1);
49 | }
50 |
51 | void BoxBarPlot::add_boxbar(BoxData& data, int size, int index)
52 | {
53 | if (m_name2series.contains(data.m_name))
54 | return;
55 |
56 | double mean, sum, min, max;
57 | QBarSet* box = new QBarSet(data.m_name);
58 | Util::cal_list(data.m_value_list, mean, sum, max, min);
59 | box->setProperty("mean", mean);
60 | box->setProperty("sum", sum);
61 | box->setProperty("min", max);
62 | box->setProperty("max", min);
63 | box->setProperty("index", index);
64 |
65 | for (int i = 0; i < size; i++)
66 | box->append(0);
67 | box->replace(index, mean);
68 |
69 | m_axisx_list.append(data.m_name);
70 | m_series->append(box);
71 |
72 |
73 | BoxBarItem* item = new BoxBarItem();
74 | item->set_chart(m_chart);
75 | item->set_data(mean, sum, min, max, index);
76 | m_chartview->add_item(item);
77 | m_name2item[data.m_name] = item;
78 |
79 | m_name2series[data.m_name] = box;
80 | }
81 |
82 | void BoxBarPlot::delete_boxbar(const QString& name)
83 | {
84 | if (!m_name2series.contains(name))
85 | return;
86 | m_series->remove(m_name2series[name]);
87 | m_name2series.remove(name);
88 |
89 | m_chartview->delete_item(m_name2item[name]);
90 | m_name2item.remove(name);
91 | }
92 |
93 | void BoxBarPlot::init_chart()
94 | {
95 | m_chart->addSeries(m_series);
96 | }
97 |
98 | void BoxBarPlot::init_axis()
99 | {
100 | m_axisX = new QBarCategoryAxis();
101 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
102 | m_series->attachAxis(m_axisX);
103 |
104 | m_axisY = new QValueAxis();
105 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
106 | m_series->attachAxis(m_axisY);
107 | }
108 |
109 | void BoxBarPlot::init_series()
110 | {
111 | m_series = new QStackedBarSeries();
112 | }
113 |
114 | BoxBarItem::BoxBarItem()
115 | {
116 | connect(this, &BoxBarItem::signal_prepare_path, this, &BoxBarItem::slot_prepare_path);
117 | }
118 |
119 | void BoxBarItem::set_chart(QChart* chart)
120 | {
121 | m_chart = chart;
122 | }
123 |
124 | void BoxBarItem::set_data(double mean, double sum, double min, double max, int index)
125 | {
126 | m_min = QPointF(index, min);
127 | m_max = QPointF(index, max);
128 | m_mean = QPointF(index, mean);
129 | m_sum = QPointF(index, sum);
130 | }
131 |
132 | void BoxBarItem::slot_prepare_path()
133 | {
134 | QLineF line(m_chart->mapToPosition(QPointF(0, 0)), m_chart->mapToPosition(QPointF(1, 0)));
135 | double width = line.length();
136 | QPointF top = m_chart->mapToPosition(m_max);
137 | QPointF buttom = m_chart->mapToPosition(m_min);
138 | QPointF center = m_chart->mapToPosition(m_mean);
139 | QPointF tl = top - QPointF(width * 0.1, 0);
140 | QPointF tr = top + QPointF(width * 0.1, 0);
141 | QPointF bl = buttom - QPointF(width * 0.1, 0);
142 | QPointF br = buttom + QPointF(width * 0.1, 0);
143 |
144 | QPainterPath path;
145 | path.moveTo(top);
146 | path.lineTo(center);
147 | path.moveTo(tl);
148 | path.lineTo(tr);
149 |
150 | m_shape = path;
151 | }
152 |
153 | QRectF BoxBarItem::boundingRect() const
154 | {
155 | emit signal_prepare_path();
156 | return m_chart->plotArea().intersected(m_shape.boundingRect());
157 | }
158 |
159 | void BoxBarItem::on_paint(QPainter* painter)
160 | {
161 | painter->setClipRect(boundingRect());
162 | painter->drawPath(m_shape);
163 | }
164 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/qq_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "qq_plot.h"
4 | #include
5 | #include "util.h"
6 | #include "tool_tip.h"
7 |
8 | QQPlot::QQPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | }
15 |
16 | QQPlot::~QQPlot()
17 | {
18 |
19 | }
20 |
21 | void QQPlot::slot_tool_tip(QPointF point, bool state)
22 | {
23 | if (m_tooltip == nullptr)
24 | m_tooltip = new ToolTip(m_chart);
25 | if (state) {
26 | m_tooltip->setText(QString("X: %1 \nY: %2% ").arg(point.x()).arg(point.y()));
27 | m_tooltip->setAnchor(point);
28 | m_tooltip->setZValue(11);
29 | m_tooltip->updateGeometry();
30 | m_tooltip->show();
31 | }
32 | else {
33 | m_tooltip->hide();
34 | }
35 | }
36 |
37 | void QQPlot::add_data(QList& list, const QString& name)
38 | {
39 | prepare_data(list);
40 |
41 | QVector line_center_poslist;
42 | QVector scatter_poslist;
43 |
44 | for (Probability& item : m_probability_list)
45 | {
46 | line_center_poslist.append(QPointF(item.theory, item.theory));
47 | scatter_poslist.append(QPointF(item.reality, item.theory));
48 | }
49 |
50 | m_line_center->replace(line_center_poslist);
51 | m_scatter->replace(scatter_poslist);
52 |
53 | m_axisX->setRange(m_min_x - 1, m_max_x + 1);
54 | m_axisY->setRange(m_min_x - 10, m_max_x + 10);
55 | }
56 |
57 | void QQPlot::init_chart()
58 | {
59 | //m_chart->legend()->hide();
60 | m_chart->addSeries(m_line_center);
61 | m_chart->addSeries(m_scatter);
62 | }
63 |
64 | void QQPlot::init_axis()
65 | {
66 | m_axisX = new QValueAxis();
67 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
68 | m_line_top->attachAxis(m_axisX);
69 | m_line_center->attachAxis(m_axisX);
70 | m_line_bottom->attachAxis(m_axisX);
71 | m_scatter->attachAxis(m_axisX);
72 |
73 | m_axisY = new QValueAxis();
74 | m_axisY->setTitleText("期望正态值");
75 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
76 | m_line_top->attachAxis(m_axisY);
77 | m_line_center->attachAxis(m_axisY);
78 | m_line_bottom->attachAxis(m_axisY);
79 | m_scatter->attachAxis(m_axisY);
80 | }
81 |
82 | void QQPlot::init_series()
83 | {
84 | m_line_center = new QLineSeries(m_chart);
85 | m_line_center->setName("参照线");
86 | m_line_center->append(QPointF(0, 0));
87 |
88 | m_line_top = new QLineSeries(m_chart);
89 | m_line_top->setName("上线百分位数");
90 | m_line_top->append(QPointF(0, 0));
91 |
92 | m_line_bottom = new QLineSeries(m_chart);
93 | m_line_bottom->setName("下线百分位数");
94 | m_line_bottom->append(QPointF(0, 0));
95 |
96 | m_scatter = new QScatterSeries();
97 | m_scatter->setName("百分数位");
98 | m_scatter->append(QPointF(0, 0));
99 | m_scatter->setMarkerSize(10);
100 | m_scatter->setBorderColor(Qt::transparent);
101 | connect(m_scatter, &QScatterSeries::hovered, this, &QQPlot::slot_tool_tip);
102 | }
103 |
104 | void QQPlot::prepare_data(QList& list)
105 | {
106 | if (list.isEmpty())
107 | return;
108 |
109 | m_n = list.count();
110 | m_mean = Util::average(list);
111 | m_variance = Util::variance(list, m_mean);
112 | m_sigma = Util::standard_deviation(list, m_variance);
113 |
114 | m_probability_list.clear();
115 |
116 | qSort(list);
117 | for (int i = 0; i < list.size(); i++)
118 | {
119 | if (list[i] < m_min_x)
120 | m_min_x = list[i];
121 | if (list[i] > m_max_x)
122 | m_max_x = list[i];
123 |
124 | Probability pro;
125 | pro.index = i + 1;
126 | pro.theory_cdf = calculate_cdf(pro.index, list.size());
127 | pro.theory_z = Util::normsinv(pro.theory_cdf);
128 | pro.theory = m_mean + pro.theory_z * m_sigma;
129 | pro.reality = list.at(i);
130 | pro.reality_z = (pro.reality - m_mean) / m_sigma;
131 | pro.reality_cdf = Util::normsdist(pro.reality_z);
132 | m_probability_list.append(pro);
133 | }
134 | }
135 |
136 | double QQPlot::calculate_cdf(int index, int n)
137 | {
138 | double value = DBL_MIN;
139 | switch (m_score_type)
140 | {
141 | case Blom:
142 | value = (index - 0.375) / (n + 0.25);
143 | break;
144 | case Benard:
145 | value = (index - 0.3) / (n + 0.4);
146 | break;
147 | case Hazen:
148 | value = (index - 0.5) / n;
149 | break;
150 | case VanDerWaerden:
151 | value = index / (n + 1);
152 | break;
153 | case KaplanMeier:
154 | value = index / n;
155 | break;
156 | default:
157 | break;
158 | }
159 | return value;
160 | }
161 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/tool_tip.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "tool_tip.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | ToolTip::ToolTip(QChart* chart, QWidget* parent)
11 | : QGraphicsItem(chart), m_chart(chart), m_widget(parent)
12 | {
13 |
14 | }
15 |
16 | ToolTip::~ToolTip()
17 | {
18 |
19 | }
20 |
21 | void ToolTip::setText(const QString& text)
22 | {
23 | m_text = text;
24 | QFontMetrics metrics(m_font);
25 | m_textRect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt::AlignLeft, m_text);
26 | m_textRect.translate(5, 5);
27 | prepareGeometryChange();
28 | m_rect = m_textRect.adjusted(-5, -5, 5, 5);
29 | }
30 |
31 | void ToolTip::setAnchor(QPointF point)
32 | {
33 | m_anchor = point;
34 | }
35 |
36 | void ToolTip::updateGeometry()
37 | {
38 | prepareGeometryChange();
39 | if (m_widget == nullptr)
40 | setPos(m_chart->mapToPosition(m_anchor) + QPoint(10, -50));
41 | else
42 | setPos(m_anchor + QPoint(10, -50));
43 | }
44 |
45 | QRectF ToolTip::boundingRect() const
46 | {
47 | QPointF anchor;
48 | if (m_widget == nullptr)
49 | anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
50 | else
51 | anchor = m_anchor;
52 | QRectF rect;
53 | rect.setLeft(qMin(m_rect.left(), anchor.x()));
54 | rect.setRight(qMax(m_rect.right(), anchor.x()));
55 | rect.setTop(qMin(m_rect.top(), anchor.y()));
56 | rect.setBottom(qMax(m_rect.bottom(), anchor.y()));
57 | return rect;
58 | }
59 |
60 | void ToolTip::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
61 | {
62 | Q_UNUSED(option);
63 | Q_UNUSED(widget);
64 | QPainterPath path;
65 | path.addRoundedRect(m_rect, 5, 5);
66 |
67 | QPointF anchor;
68 | if (m_widget == nullptr)
69 | anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
70 | else
71 | anchor = m_anchor;
72 | if (!m_rect.contains(anchor) && !m_anchor.isNull()) {
73 | QPointF point1, point2;
74 |
75 | // establish the position of the anchor point in relation to m_rect
76 | bool above = anchor.y() <= m_rect.top();
77 | bool aboveCenter = anchor.y() > m_rect.top() && anchor.y() <= m_rect.center().y();
78 | bool belowCenter = anchor.y() > m_rect.center().y() && anchor.y() <= m_rect.bottom();
79 | bool below = anchor.y() > m_rect.bottom();
80 |
81 | bool onLeft = anchor.x() <= m_rect.left();
82 | bool leftOfCenter = anchor.x() > m_rect.left() && anchor.x() <= m_rect.center().x();
83 | bool rightOfCenter = anchor.x() > m_rect.center().x() && anchor.x() <= m_rect.right();
84 | bool onRight = anchor.x() > m_rect.right();
85 |
86 | // get the nearest m_rect corner.
87 | qreal x = (onRight + rightOfCenter) * m_rect.width();
88 | qreal y = (below + belowCenter) * m_rect.height();
89 | bool cornerCase = (above && onLeft) || (above && onRight) || (below && onLeft) || (below && onRight);
90 | bool vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y);
91 |
92 | qreal x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * !vertical * (onLeft * 10 - onRight * 20);
93 | qreal y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20);;
94 | point1.setX(x1);
95 | point1.setY(y1);
96 |
97 | qreal x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * !vertical * (onLeft * 20 - onRight * 10);;
98 | qreal y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10);;
99 | point2.setX(x2);
100 | point2.setY(y2);
101 |
102 | if (m_widget == nullptr)
103 | {
104 | path.moveTo(point1);
105 | path.lineTo(anchor);
106 | path.lineTo(point2);
107 | path = path.simplified();
108 | }
109 | //else
110 | //{
111 | // path.moveTo(point1);
112 | // path.lineTo(anchor);
113 | // path.lineTo(point2);
114 | // path = path.simplified();
115 | //}
116 | }
117 | painter->setBrush(QColor(255, 255, 255));
118 | painter->drawPath(path);
119 | painter->drawText(m_textRect, m_text);
120 | }
121 |
122 | void ToolTip::mousePressEvent(QGraphicsSceneMouseEvent* event)
123 | {
124 | event->setAccepted(true);
125 | }
126 |
127 | void ToolTip::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
128 | {
129 | if (event->buttons() & Qt::LeftButton) {
130 | setPos(mapToParent(event->pos() - event->buttonDownPos(Qt::LeftButton)));
131 | event->setAccepted(true);
132 | }
133 | else {
134 | event->setAccepted(false);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/probability_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "probability_plot.h"
4 | #include
5 | #include "util.h"
6 | #include "tool_tip.h"
7 |
8 | ProbabilityPlot::ProbabilityPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | }
15 |
16 | ProbabilityPlot::~ProbabilityPlot()
17 | {
18 | }
19 |
20 | void ProbabilityPlot::slot_tool_tip(QPointF point, bool state)
21 | {
22 | if (m_tooltip == nullptr)
23 | m_tooltip = new ToolTip(m_chart);
24 | if (state) {
25 | m_tooltip->setText(QString("X: %1 \nY: %2% ").arg(point.x()).arg(Util::normsdist(point.y())*100));
26 | m_tooltip->setAnchor(point);
27 | m_tooltip->setZValue(11);
28 | m_tooltip->updateGeometry();
29 | m_tooltip->show();
30 | }
31 | else {
32 | m_tooltip->hide();
33 | }
34 | }
35 |
36 | void ProbabilityPlot::add_data(QList& list, const QString& name)
37 | {
38 | prepare_data(list);
39 |
40 | QVector line_center_poslist;
41 | QVector scatter_poslist;
42 |
43 | for (Probability &item : m_probability_list)
44 | {
45 | line_center_poslist.append(QPointF(item.theory,item.theory_z));
46 | scatter_poslist.append(QPointF(item.reality, item.theory_z));
47 | }
48 |
49 | m_line_center->replace(line_center_poslist);
50 | m_scatter->replace(scatter_poslist);
51 |
52 | m_axisX->setRange(m_min_x - 1, m_max_x + 1);
53 | }
54 |
55 | void ProbabilityPlot::init_chart()
56 | {
57 | //m_chart->legend()->hide();
58 | m_chart->addSeries(m_line_center);
59 | m_chart->addSeries(m_scatter);
60 | }
61 |
62 | void ProbabilityPlot::init_axis()
63 | {
64 | m_axisX = new QValueAxis();
65 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
66 | m_line_top->attachAxis(m_axisX);
67 | m_line_center->attachAxis(m_axisX);
68 | m_line_bottom->attachAxis(m_axisX);
69 | m_scatter->attachAxis(m_axisX);
70 |
71 | m_axisY = new QCategoryAxis();
72 | m_axisY->setTitleText("百分比");
73 | m_axisY->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);
74 | m_axisY->setMin(-3.09);
75 | m_axisY->setMax(3.09);
76 | m_axisY->setStartValue(-3.71);
77 | m_axisY->append("0.1", -3.09);
78 | m_axisY->append("1", -2.33);
79 | m_axisY->append("5", -1.64);
80 | m_axisY->append("10", -1.28);
81 | m_axisY->append("20", -0.84);
82 | m_axisY->append("30", -0.52);
83 | m_axisY->append("40", -0.25);
84 | m_axisY->append("50", 0);
85 | m_axisY->append("60", 0.25);
86 | m_axisY->append("70", 0.52);
87 | m_axisY->append("80", 0.84);
88 | m_axisY->append("90", 1.28);
89 | m_axisY->append("95", 1.64);
90 | m_axisY->append("99", 2.33);
91 | m_axisY->append("99.9", 3.09);
92 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
93 | m_line_top->attachAxis(m_axisY);
94 | m_line_center->attachAxis(m_axisY);
95 | m_line_bottom->attachAxis(m_axisY);
96 | m_scatter->attachAxis(m_axisY);
97 | }
98 |
99 | void ProbabilityPlot::init_series()
100 | {
101 | m_line_center = new QLineSeries(m_chart);
102 | m_line_center->setName("参照线");
103 | m_line_center->append(QPointF(0, 0));
104 |
105 | m_line_top = new QLineSeries(m_chart);
106 | m_line_top->setName("上线百分位数");
107 | m_line_top->append(QPointF(0, 0));
108 |
109 | m_line_bottom = new QLineSeries(m_chart);
110 | m_line_bottom->setName("下线百分位数");
111 | m_line_bottom->append(QPointF(0, 0));
112 |
113 | m_scatter = new QScatterSeries();
114 | m_scatter->setName("百分数位");
115 | m_scatter->append(QPointF(0, 0));
116 | m_scatter->setMarkerSize(10);
117 | m_scatter->setBorderColor(Qt::transparent);
118 | connect(m_scatter, &QScatterSeries::hovered, this, &ProbabilityPlot::slot_tool_tip);
119 | }
120 |
121 | void ProbabilityPlot::prepare_data(QList& list)
122 | {
123 | if (list.isEmpty())
124 | return;
125 |
126 | m_n = list.count();
127 | m_mean = Util::average(list);
128 | m_variance = Util::variance(list, m_mean);
129 | m_sigma = Util::standard_deviation(list, m_variance);
130 |
131 | m_probability_list.clear();
132 |
133 | qSort(list);
134 | for (int i = 0; i < list.size(); i++)
135 | {
136 | if (list[i] < m_min_x)
137 | m_min_x = list[i];
138 | if (list[i] > m_max_x)
139 | m_max_x = list[i];
140 |
141 | Probability pro;
142 | pro.index = i + 1;
143 | pro.theory_cdf = calculate_cdf(pro.index, list.size());
144 | pro.theory_z = Util::normsinv(pro.theory_cdf);
145 | pro.theory = m_mean + pro.theory_z * m_sigma;
146 | pro.reality = list.at(i);
147 | pro.reality_z = (pro.reality - m_mean) / m_sigma;
148 | //pro.reality_cdf = Util::normsdist(pro.reality_z);
149 | m_probability_list.append(pro);
150 | }
151 | }
152 |
153 | double ProbabilityPlot::calculate_cdf(int index, int n)
154 | {
155 | double value = DBL_MIN;
156 | switch (m_score_type)
157 | {
158 | case Blom:
159 | value= (index - 0.375) / (n + 0.25);
160 | break;
161 | case Benard:
162 | value = (index - 0.3) / (n + 0.4);
163 | break;
164 | case Hazen:
165 | value = (index - 0.5) / n;
166 | break;
167 | case VanDerWaerden:
168 | value = index / (n + 1);
169 | break;
170 | case KaplanMeier:
171 | value = index / n;
172 | break;
173 | default:
174 | break;
175 | }
176 | return value;
177 | }
178 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/waterfall_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "waterfall_plot.h"
4 | #include "chart_view.h"
5 | #include "plot.h"
6 | #include
7 |
8 | WaterfallPlot::WaterfallPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | init_item();
15 | }
16 |
17 | WaterfallPlot::~WaterfallPlot()
18 | {
19 |
20 | }
21 |
22 | void WaterfallPlot::set_data(QList& value_list)
23 | {
24 | QList start_pos, end_pos, add_pos, low_pos;
25 |
26 | double sum = start_value;
27 | m_axis_list.append(tr("起始值"));
28 | start_pos.append(QPointF(0, 0));
29 | start_pos.append(QPointF(0, sum));
30 |
31 | m_max_y = m_min_y = start_value;
32 | for (int i = 0; i < value_list.size(); i++)
33 | {
34 | if (value_list[i].m_value >= 0)
35 | {
36 | add_pos.append(QPointF(i + 1, sum + value_list[i].m_value));
37 | add_pos.append(QPointF(i + 1, sum));
38 | }
39 | else
40 | {
41 | low_pos.append(QPointF(i + 1, sum));
42 | low_pos.append(QPointF(i + 1, sum - value_list[i].m_value));
43 | }
44 | sum += value_list[i].m_value;
45 |
46 | if (sum > m_max_y)
47 | m_max_y = sum;
48 | if (sum < m_min_y)
49 | m_min_y = sum;
50 |
51 | m_axis_list.append(value_list[i].m_name);
52 | }
53 |
54 | m_axis_list.append(tr("累计值"));
55 | end_pos.append(QPointF(value_list.size() + 1, 0));
56 | end_pos.append(QPointF(value_list.size() + 1, sum));
57 |
58 | m_item_start->set_data(start_pos);
59 | m_item_end->set_data(end_pos);
60 | m_item_add->set_data(add_pos);
61 | m_item_low->set_data(low_pos);
62 |
63 | m_axisX->append(m_axis_list);
64 | m_axisX->setRange(m_axis_list.first(), m_axis_list.last());
65 | m_axisY->setRange(m_min_y * 0.9, m_max_y * 1.1);
66 | }
67 |
68 | void WaterfallPlot::clear_data()
69 | {
70 |
71 | }
72 |
73 | void WaterfallPlot::init_chart()
74 | {
75 | m_chart->addSeries(m_bar);
76 | }
77 |
78 | void WaterfallPlot::init_axis()
79 | {
80 | m_axisX = new QBarCategoryAxis();
81 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
82 | m_bar->attachAxis(m_axisX);
83 |
84 | m_axisY = new QValueAxis();
85 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
86 | m_bar->attachAxis(m_axisY);
87 | }
88 |
89 | void WaterfallPlot::init_series()
90 | {
91 | m_bar = new QBarSeries();
92 | m_bar_start = new QBarSet(tr("起始"));
93 | m_bar_add = new QBarSet(tr("增加"));
94 | m_bar_low = new QBarSet(tr("降低"));
95 | m_bar_end = new QBarSet(tr("累计"));
96 | m_bar->append(m_bar_start);
97 | m_bar->append(m_bar_add);
98 | m_bar->append(m_bar_low);
99 | m_bar->append(m_bar_end);
100 | }
101 |
102 | void WaterfallPlot::init_item()
103 | {
104 | m_item_start = new WaterfallItem();
105 | m_item_start->set_chart(m_chart);
106 | m_item_start->set_series(m_bar_start);
107 | m_chartview->add_item(m_item_start);
108 |
109 | m_item_end = new WaterfallItem();
110 | m_item_end->set_chart(m_chart);
111 | m_item_end->set_series(m_bar_end);
112 | m_chartview->add_item(m_item_end);
113 |
114 | m_item_add = new WaterfallItem();
115 | m_item_add->set_chart(m_chart);
116 | m_item_add->set_series(m_bar_add);
117 | m_chartview->add_item(m_item_add);
118 |
119 | m_item_low = new WaterfallItem();
120 | m_item_low->set_chart(m_chart);
121 | m_item_low->set_series(m_bar_low);
122 | m_chartview->add_item(m_item_low);
123 | }
124 |
125 | //////////////////////////////////////////////////////////////////////////////
126 | /// 瀑布图
127 | WaterfallItem::WaterfallItem()
128 | {
129 | connect(this, &WaterfallItem::signal_prepare_path, this, &WaterfallItem::slot_prepare_path);
130 | }
131 |
132 | void WaterfallItem::set_chart(QChart* chart)
133 | {
134 | m_chart = chart;
135 | }
136 |
137 | void WaterfallItem::set_data(QList data)
138 | {
139 | m_data = data;
140 | }
141 |
142 | void WaterfallItem::set_series(QBarSet* series)
143 | {
144 | m_series = series;
145 | }
146 |
147 | void WaterfallItem::slot_prepare_path()
148 | {
149 | QPainterPath path;
150 |
151 | QLineF line(m_chart->mapToPosition(QPointF(0, 0)), m_chart->mapToPosition(QPointF(1, 0)));
152 | double width = line.length();
153 | for (int i = 0; i < m_data.size(); i=i+2)
154 | {
155 | QPointF top = m_data[i].y()>= m_data[i + 1].y() ? m_chart->mapToPosition(m_data[i]) : m_chart->mapToPosition(m_data[i + 1]);
156 | QPointF buttom = m_data[i].y() < m_data[i + 1].y() ? m_chart->mapToPosition(m_data[i]) : m_chart->mapToPosition(m_data[i + 1]);
157 | QPointF tl = top - QPointF(width * 0.05, 0);
158 | QPointF tr = top + QPointF(width * 0.05, 0);
159 | QPointF bl = buttom - QPointF(width * 0.05, 0);
160 | QPointF br = buttom + QPointF(width * 0.05, 0);
161 | QRectF rect(tl, br);
162 | path.addRect(rect);
163 | }
164 |
165 | m_shape = path;
166 | }
167 |
168 | QRectF WaterfallItem::boundingRect() const
169 | {
170 | emit signal_prepare_path();
171 | return m_chart->plotArea().intersected(m_shape.boundingRect());
172 | }
173 |
174 | void WaterfallItem::on_paint(QPainter* painter)
175 | {
176 | painter->setClipRect(boundingRect());
177 |
178 | QColor color = m_series->color();
179 |
180 | //QPen pen;
181 | //pen.setColor(color);
182 | //pen.setStyle(Qt::SolidLine);
183 | //painter->setPen(pen);
184 |
185 | QBrush brush;
186 | brush.setStyle(Qt::SolidPattern);
187 | brush.setColor(color);
188 | painter->setBrush(brush);
189 |
190 | painter->drawPath(m_shape);
191 | }
192 |
--------------------------------------------------------------------------------
/projects/Graph/src/util/util.cpp:
--------------------------------------------------------------------------------
1 | #include "util.h"
2 |
3 | #include
4 | #include
5 | #include "qmath.h"
6 |
7 | QRectF Util::bounding_rect(const QList& points)
8 | {
9 | double xmin, xmax, ymin, ymax;
10 | bounding_rect(points, xmin, xmax, ymin, ymax);
11 | return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
12 | }
13 |
14 | void Util::bounding_rect(const QList& points, double& xmin, double& xmax, double& ymin, double& ymax)
15 | {
16 | xmin = INT_MAX;
17 | xmax = INT_MIN;
18 | ymin = INT_MAX;
19 | ymax = INT_MIN;
20 |
21 | for (auto& p : points)
22 | {
23 | if (p.x() < xmin) xmin = p.x();
24 | if (p.x() > xmax) xmax = p.x();
25 | if (p.y() < ymin) ymin = p.y();
26 | if (p.y() > ymax) ymax = p.y();
27 | }
28 | if (xmin == xmax)
29 | xmax += 0.01;
30 | if (ymin == ymax)
31 | ymax += 0.01;
32 | }
33 |
34 | QRectF Util::bounding_rect(const QList& rects)
35 | {
36 | QList pts;
37 | for (auto r : rects)
38 | {
39 | pts.append(r.topLeft());
40 | pts.append(r.bottomRight());
41 | }
42 | return Util::bounding_rect(pts);
43 | }
44 |
45 | void Util::bounding_rect(const QRectF& rect,
46 | double& xmin, double& xmax, double& ymin, double& ymax)
47 | {
48 | QList pts;
49 | pts.append(rect.topLeft());
50 | pts.append(rect.bottomRight());
51 | bounding_rect(pts, xmin, xmax, ymin, ymax);
52 | }
53 |
54 |
55 | double Util::angle(const QPointF& p1, const QPointF& p2)
56 | {
57 | //QLineF基于y轴向下,而我们是y轴向上,所以需要变化y轴的方向
58 | QPointF _p1 = QPointF(p1.x(), -p1.y());
59 | QPointF _p2 = QPointF(p2.x(), -p2.y());
60 | return QLineF(_p1, _p2).angle();
61 | }
62 |
63 | QPointF Util::rotated(const QPointF& p, double angle)
64 | {
65 | double rad = angle * ADEGREE;
66 | QMatrix mat(cos(rad),sin(rad), -sin(rad), cos(rad),0,0);
67 | return mat.map(p);
68 | }
69 |
70 | double Util::average(QList& list)
71 | {
72 | double sum = 0;
73 | for (int i = 0; i < list.size(); i++) // 求和
74 | sum += list[i];
75 | return sum / list.size();
76 | }
77 |
78 | double Util::max(QList& list)
79 | {
80 | double max = DBL_MIN;
81 | for (auto& item : list)
82 | {
83 | if (max < item)
84 | max = item;
85 | }
86 | return max;
87 | }
88 |
89 | double Util::min(QList& list)
90 | {
91 | double min = DBL_MAX;
92 | for (auto& item : list)
93 | {
94 | if (min > item)
95 | min = item;
96 | }
97 | return min;
98 | }
99 |
100 | void Util::cal_list(QList& list, double& mean, double& sum, double& max, double& min)
101 | {
102 | min = DBL_MAX; max = DBL_MIN; sum = 0;
103 | for (int i = 0; i < list.size(); i++) // 求和
104 | {
105 | if (max < list[i])
106 | max = list[i];
107 | if (min > list[i])
108 | min = list[i];
109 | sum += list[i];
110 | }
111 | mean = sum / list.size();
112 | }
113 |
114 | double Util::variance(QList& list, double mean/*= DBL_MIN*/)
115 | {
116 | double sum = 0;
117 | double average = mean != DBL_MIN ? mean : Util::average(list);
118 | for (int i = 0; i < list.size(); i++)
119 | sum += pow(list[i] - average, 2);
120 | return sum / (list.size() - 1);
121 | }
122 |
123 | double Util::standard_deviation(QList& list, double sigma2 /*= DBL_MIN*/)
124 | {
125 | double variance = sigma2 != DBL_MIN ? sigma2 : Util::variance(list);
126 | return sqrt(variance);
127 | }
128 |
129 | double Util::normal_cdf(double value)
130 | {
131 | return 0.5 * erfc(-value * M_SQRT1_2);
132 | }
133 |
134 | double Util::normal_z(double value)
135 | {
136 | const double A1 = 0.31938153;
137 | const double A2 = -0.356563782;
138 | const double A3 = 1.781477937;
139 | const double A4 = -1.821255978;
140 | const double A5 = 1.330274429;
141 | const double RSQRT2PI = 0.39894228040143267793994605993438;
142 |
143 | double
144 | K = 1.0 / (1.0 + 0.2316419 * fabs(value));
145 |
146 | double
147 | cnd = RSQRT2PI * exp(-0.5 * value * value) *
148 | (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))));
149 |
150 | if (value > 0)
151 | cnd = 1.0 - cnd;
152 |
153 | return cnd;
154 | }
155 |
156 | double Util::normsdist(double z)
157 | {
158 | if (z > 6)
159 | return 1;
160 | if (z < -6)
161 | return 0;
162 | double gamma = 0.231641900, a1 = 0.319381530, a2 = -0.356563782, a3 = 1.781477973, a4 = -1.821255978, a5 = 1.330274429;
163 | double x = abs(z);
164 | double t = 1 / (1 + gamma * x);
165 | double n = 1 - (1 / (sqrt(2 * PI)) * exp(-z * z / 2)) * (a1 * t + a2 * pow(t, 2) + a3 * pow(t, 3) + a4 * pow(t, 4) + a5 * pow(t, 5));
166 | if (z < 0)
167 | return 1.0 - n;
168 | return n;
169 | }
170 |
171 | double Util::normsinv(double p)
172 | {
173 | double LOW = 0.02425;
174 | double HIGH = 0.97575;
175 | double a[] = { -3.969683028665376e+01, 2.209460984245205e+02,-2.759285104469687e+02, 1.383577518672690e+02,-3.066479806614716e+01, 2.506628277459239e+00 };
176 | double b[] = { -5.447609879822406e+01, 1.615858368580409e+02,-1.556989798598866e+02, 6.680131188771972e+01,-1.328068155288572e+01 };
177 | double c[] = { -7.784894002430293e-03, -3.223964580411365e-01,-2.400758277161838e+00, -2.549732539343734e+00,4.374664141464968e+00, 2.938163982698783e+00 };
178 | double d[] = { 7.784695709041462e-03, 3.224671290700398e-01,2.445134137142996e+00, 3.754408661907416e+00 };
179 | double q, r;
180 | if (p < LOW) {
181 | q = sqrt(-2 * log(p));
182 | return (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
183 | }
184 | else if (p > HIGH) {
185 | q = sqrt(-2 * log(1 - p));
186 | return -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
187 | }
188 | else {
189 | q = p - 0.5;
190 | r = q * q;
191 | return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1);
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/histogram_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "histogram_plot.h"
4 | #include "chart_view.h"
5 | #include
6 | #include
7 |
8 | HistogramPlot::HistogramPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | }
15 |
16 | HistogramPlot::~HistogramPlot()
17 | {
18 |
19 | }
20 |
21 | void HistogramPlot::add_histogram(QList& value_list, const QString& name)
22 | {
23 | if (m_name2itemlist.contains(name))
24 | return;
25 |
26 | QList> list = prepare_data(value_list);
27 |
28 | Histogram* his = new Histogram;
29 | his->m_index = m_name2itemlist.size() + 1;
30 | his->m_value = value_list;
31 | QScatterSeries *series = new QScatterSeries();
32 | series->setName(name);
33 | series->setColor(QColor::colorNames()[m_name2itemlist.size() + 5]);
34 | m_chart->addSeries(series);
35 | series->attachAxis(m_axisX);
36 | series->attachAxis(m_axisY);
37 | his->m_series = series;
38 | for (int i = 0; i < list.size(); i++)
39 | {
40 | if (list[i][2] > m_count)
41 | m_count = list[i][2];
42 | QVector ver;
43 | ver.append(list[i][0]); //开始
44 | ver.append(list[i][1]); //结束
45 | ver.append(list[i][2]); //总数
46 |
47 | HistogramItem* item = new HistogramItem();
48 | item->set_chart(m_chart);
49 | item->set_data(ver);
50 | item->set_index(his->m_index);
51 | m_chartview->add_item(item);
52 | his->m_list.append(item);
53 | }
54 | m_name2itemlist[name] = his;
55 |
56 | m_chart->setProperty("sum", m_name2itemlist.size());
57 |
58 | m_axisX->setTickCount(list.size()+1);
59 | m_max_x = m_min_x + list.size() * m_interval;
60 | m_axisX->setRange(m_min_x, m_max_x);
61 | m_axisY->setTickCount(m_count+2);
62 | m_axisY->setRange(0, m_count+1);
63 | }
64 |
65 | void HistogramPlot::delete_histogram(const QString& name)
66 | {
67 | if (!m_name2itemlist.contains(name))
68 | return;
69 | m_chart->removeSeries(m_name2itemlist[name]->m_series);
70 | DELETE_PTR_LIST(m_name2itemlist[name]->m_list);
71 | DELETE_PTR(m_name2itemlist[name]);
72 | m_name2itemlist.remove(name);
73 | }
74 |
75 | void HistogramPlot::init_chart()
76 | {
77 | //m_chart->legend()->hide();
78 | //m_chart->addSeries(m_series);
79 | }
80 |
81 | void HistogramPlot::init_axis()
82 | {
83 | m_axisX = new QValueAxis();
84 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
85 | //m_series->attachAxis(m_axisX);
86 |
87 | m_axisY = new QValueAxis();
88 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
89 | //m_series->attachAxis(m_axisY);
90 | }
91 |
92 | void HistogramPlot::init_series()
93 | {
94 | //m_series = new QScatterSeries();
95 | }
96 |
97 | QList> HistogramPlot::prepare_data(QList& list)
98 | {
99 | if (m_name2itemlist.isEmpty())
100 | {
101 | for (auto& item : list)
102 | {
103 | if (item < m_min_x)
104 | m_min_x = item;
105 | if (item > m_max_x)
106 | m_max_x = item;
107 | }
108 |
109 | if ((floor((m_max_x - m_min_x) / m_interval)) * m_interval + m_min_x >= m_max_x)
110 | m_max_x = m_max_x + m_interval;
111 |
112 | QList> histogram_list;
113 | for (double i = m_min_x; i < m_max_x; i = i + m_interval)
114 | {
115 | QVector vect(3);
116 | vect[0] = i;
117 | vect[1] = i + m_interval;
118 | vect[2] = 0;
119 | histogram_list.append(vect);
120 | }
121 |
122 | for (int i = 0; i < list.size(); i++)
123 | {
124 | int index = floor((list[i] - m_min_x) / m_interval);
125 | if (index * m_interval + m_min_x < list[i])
126 | histogram_list[index--][2]++;
127 | else
128 | histogram_list[index][2]++;
129 | }
130 | return histogram_list;
131 | }
132 | else
133 | {
134 | double min = m_min_x, max = m_max_x;
135 | for (auto& item : list)
136 | {
137 | if (item < min)
138 | min = item;
139 | if (item > max)
140 | max = item;
141 | }
142 | while ( min< m_min_x)
143 | m_min_x -= m_interval;
144 | while (max>= m_max_x)
145 | m_max_x += m_interval;
146 |
147 | QList> histogram_list;
148 | for (double i = m_min_x; i < m_max_x; i = i + m_interval)
149 | {
150 | QVector vect(3);
151 | vect[0] = i;
152 | vect[1] = i + m_interval;
153 | vect[2] = 0;
154 | histogram_list.append(vect);
155 | }
156 |
157 | for (int i = 0; i < list.size(); i++)
158 | {
159 | int index = floor((list[i] - m_min_x) / m_interval);
160 | if (index * m_interval + m_min_x < list[i])
161 | histogram_list[index--][2]++;
162 | else
163 | histogram_list[index][2]++;
164 | }
165 | return histogram_list;
166 | }
167 | }
168 |
169 | //////////////////////////////////////////////////////////////////////////////
170 | /// 直方图
171 | HistogramItem::HistogramItem()
172 | {
173 | connect(this, &HistogramItem::signal_prepare_path, this, &HistogramItem::slot_prepare_path);
174 | }
175 |
176 | void HistogramItem::set_chart(QChart* chart)
177 | {
178 | m_chart = chart;
179 | }
180 |
181 | void HistogramItem::set_data(QVector data)
182 | {
183 | m_data = data;
184 | }
185 |
186 | void HistogramItem::set_index(int index)
187 | {
188 | m_index = index - 1;
189 | }
190 |
191 | void HistogramItem::slot_prepare_path()
192 | {
193 | QPainterPath path;
194 |
195 | int size = m_chart->property("sum").toInt();
196 | double width = (m_data[1] - m_data[0]) / size;
197 | double start = m_data[0] + width * m_index;
198 | double end = start + width;
199 | QPointF tl = m_chart->mapToPosition(QPointF(start, m_data[2]));
200 | QPointF br = m_chart->mapToPosition(QPointF(end, 0));
201 | QRectF rect(tl, br);
202 | path.addRect(rect);
203 |
204 | m_shape = path;
205 | }
206 |
207 | QRectF HistogramItem::boundingRect() const
208 | {
209 | emit signal_prepare_path();
210 | return m_chart->plotArea().intersected(m_shape.boundingRect());
211 | }
212 |
213 | void HistogramItem::on_paint(QPainter* painter)
214 | {
215 | painter->setClipRect(boundingRect());
216 |
217 | QColor color(QColor::colorNames()[m_index + 5]);
218 |
219 | //QPen pen;
220 | //pen.setColor(color);
221 | //pen.setStyle(Qt::SolidLine);
222 | //painter->setPen(pen);
223 |
224 | QBrush brush;
225 | brush.setStyle(Qt::SolidPattern);
226 | brush.setColor(color);
227 | painter->setBrush(brush);
228 |
229 | painter->drawPath(m_shape);
230 | }
231 |
--------------------------------------------------------------------------------
/projects/Test/src/main_window.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 549
10 | 456
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 |
19 |
29 |
30 |
31 | TopToolBarArea
32 |
33 |
34 | false
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 线
49 |
50 |
51 |
52 |
53 | 删除
54 |
55 |
56 |
57 |
58 | 线
59 |
60 |
61 | 线
62 |
63 |
64 |
65 |
66 | 箭头
67 |
68 |
69 |
70 |
71 | 水平分割
72 |
73 |
74 |
75 |
76 | 垂直分割
77 |
78 |
79 |
80 |
81 | 删除分割
82 |
83 |
84 |
85 |
86 | 添加Label
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | action_add_line
95 | triggered()
96 | MainWindow
97 | slot_add_line()
98 |
99 |
100 | -1
101 | -1
102 |
103 |
104 | 199
105 | 149
106 |
107 |
108 |
109 |
110 | action_delete_line
111 | triggered()
112 | MainWindow
113 | slot_delete_line()
114 |
115 |
116 | -1
117 | -1
118 |
119 |
120 | 199
121 | 149
122 |
123 |
124 |
125 |
126 | action_draw_arrows
127 | triggered()
128 | MainWindow
129 | slot_draw_arrows()
130 |
131 |
132 | -1
133 | -1
134 |
135 |
136 | 274
137 | 227
138 |
139 |
140 |
141 |
142 | action_draw_line
143 | triggered()
144 | MainWindow
145 | slot_draw_line()
146 |
147 |
148 | -1
149 | -1
150 |
151 |
152 | 274
153 | 227
154 |
155 |
156 |
157 |
158 | horizontal_action
159 | triggered()
160 | MainWindow
161 | slot_horizontal_splitter()
162 |
163 |
164 | -1
165 | -1
166 |
167 |
168 | 274
169 | 227
170 |
171 |
172 |
173 |
174 | vertical_action
175 | triggered()
176 | MainWindow
177 | slot_vertical_splitter()
178 |
179 |
180 | -1
181 | -1
182 |
183 |
184 | 274
185 | 227
186 |
187 |
188 |
189 |
190 | action_add
191 | triggered()
192 | MainWindow
193 | slot_add_label()
194 |
195 |
196 | -1
197 | -1
198 |
199 |
200 | 274
201 | 227
202 |
203 |
204 |
205 |
206 | delete_action
207 | triggered()
208 | MainWindow
209 | slot_delete_splitter()
210 |
211 |
212 | -1
213 | -1
214 |
215 |
216 | 274
217 | 227
218 |
219 |
220 |
221 |
222 |
223 | slot_add_line()
224 | slot_delete_line()
225 | slot_draw_line()
226 | slot_draw_arrows()
227 | slot_vertical_splitter()
228 | slot_horizontal_splitter()
229 | slot_delete_splitter()
230 | slot_add_label()
231 |
232 |
233 |
--------------------------------------------------------------------------------
/projects/Graph/src/chart/stock_plot.cpp:
--------------------------------------------------------------------------------
1 | #pragma execution_character_set("utf-8")
2 |
3 | #include "stock_plot.h"
4 | #include
5 | #include "tool_tip.h"
6 | #include "chart_view.h"
7 |
8 | StockPlot::StockPlot(QWidget *parent)
9 | : Plot(parent)
10 | {
11 | init_series();
12 | init_chart();
13 | init_axis();
14 | }
15 |
16 | StockPlot::~StockPlot()
17 | {
18 | //QCandlestickSeries常用函数:
19 | //append(self, set):将由set指定的单个烛台条目添加到烛台图中,并获得其所有权。如果该项为空或已在系列中,则不会附加该项。如果添加成功返回True,否则返回False。
20 | //clear(self) : 永久删除图中的所有条目。
21 | //remove(self, set):从烛台图中删除set指定的条目。
22 | //take(self, set):从图中获取由set指定的单个条目。但不删除该条目。
23 | //setBodyOutlineVisible(self, bodyOutlineVisible):设置烛台轮廓是否可见。
24 | //setBodyWidth(self, bodyWidth):设置烛台条目的相对宽度,范围为0.0到1.0。
25 | //setBrush(self, brush):设置烛台条目的画刷。
26 | //setPen(self, pen):设置烛台条目线条的画笔。
27 | //setCapsVisible(self, capsVisible):设置烛台条目盖是否可见。
28 | //setCapsWidth(self, capsWidth): 设置烛台条目盖的宽度。
29 | //setDecreasingColor(self, decreasingColor):设置烛台条目递减颜色。
30 | //setIncreasingColor(self, increasingColor):设置烛台条目递增颜色。
31 | //setMaximumColumnWidth(self, maximumColumnWidth):设置烛台条目的最大宽度(以像素为单位。设置为负值表示没有最大宽度。所有负值都将转换为 - 1.0)。
32 | //setMinimumColumnWidth(self, minimumColumnWidth):设置烛台条目的最小宽度(以像素为单位。设置为负值表示没有最大宽度。所有负值都将转换为 - 1.0)。
33 |
34 | //QCandlestickSeries常用信号:
35 | //bodyOutlineVisibilityChanged(self):烛台条目主体轮廓的可见性更改时,将发出此信号。
36 | //bodyWidthChanged(self):烛台条目的宽度更改时,将发出此信号。
37 | //brushChanged(self):烛台条目画刷更改时,将发出此信号。
38 | //candlestickSetsAdded(self, sets):当sets指定的烛台条目添加到烛台图中时,将发出此信号。
39 | //candlestickSetsRemoved(self, sets):从烛台图中删除sets指定的烛台条目时,将发出此信号。
40 | //capsVisibilityChanged(self):烛台条目盖的可见属性更改时,将发出此信号。
41 | //capsWidthChanged(self) : 烛台条目盖的宽度更改时,将发出此信号。
42 | //clicked(self, set) : 单击图表上由set指定的烛台条目时,将发出此信号。
43 | //countChanged(self):当烛台图中中烛台条目的数量发生更改时,将发出此信号。
44 | //decreasingColorChanged(self) : 当烛台条目的颜色减少时,将发出此信号。
45 | //doubleClicked(self, set):双击图表上由set指定的烛台条目时,将发出此信号。
46 | //hovered(self, status, set):当鼠标悬停在所指定的烛台条目set时,这个信号被发射。当鼠标移至该条目上方时,state变为True,而当鼠标再次移开时,state变为False。
47 | //increasingColorChanged(self):烛台条目颜色增加时,将发出此信号。
48 | //maximumColumnWidthChanged(self) : 烛台条目的最大列宽发生变化时,将发出此信号。
49 | //minimumColumnWidthChanged(self):烛台条目的最小列宽发生变化时,将发出此信号。
50 | //penChanged(self):烛台图的画笔发生更改时会发出此信号。
51 | //pressed(self, set):当用户单击set指定的烛台条目并按住鼠标按钮时,将发出此信号。
52 | //released(self, set):当用户释放set所指定的烛台条目上的鼠标时,将发出此信号。
53 |
54 | //QCandlestickSet常用函数:
55 | //setBrush(self, brush):设置条目的画刷为brush。
56 | //setPen(self, pen):设置条目的画笔为pen。
57 | //setClose(self, close):设置条目的收盘价为close。
58 | //setHigh(self, high):设置条目的上限值为high。
59 | //setLow(self, low):设置条目的下限值为low。
60 | //setOpen(self, open):设置条目的开盘价。
61 | //setTimestamp(self, timestamp):设置条目的时间戳。
62 |
63 | //QCandlestickSet常用信号:
64 | //brushChanged(self):更改时画刷,将发出此信号。
65 | //penChanged(self):更改画笔时,将发出此信号。
66 | //clicked(self):单击条目时,将发出此信号。
67 | //doubleClicked(self):双击条目时,将发出此信号。
68 | //hovered(self, status):当鼠标悬停在条目上时,将发出此信号。
69 | //pressed(self):当用户单击条并按住鼠标按钮时,将发出此信号。
70 | //released(self):当用户释放对条目的释放鼠标时,将发出此信号。
71 | //closeChanged(self):条目收盘价发生改变时发出此信号。
72 | //highChanged(self):条目上限值更改时,将发出此信号。
73 | //lowChanged(self):条目下限值更改时,将发出此信号。
74 | //openChanged(self):条目开盘价变化时发出此信号。
75 | //timestampChanged(self):当条目时间戳更改时,将发出此信号。
76 | }
77 |
78 | void StockPlot::slot_tool_tip(bool status, QCandlestickSet* set)
79 | {
80 | if (m_tooltip == nullptr)
81 | m_tooltip = new ToolTip(m_chart,this);
82 | if (status) {
83 | m_tooltip->setText(QString("开盘: %1 \n收盘: %2\n最高: %3\n最低: %4 ")
84 | .arg(set->open()).arg(set->close()).arg(set->high()).arg(set->low()));
85 | QPointF point = m_chartview->mapFromGlobal(QCursor::pos());
86 | m_tooltip->setAnchor(point);
87 | m_tooltip->setZValue(11);
88 | m_tooltip->updateGeometry();
89 | m_tooltip->show();
90 | }
91 | else
92 | m_tooltip->hide();
93 | }
94 |
95 | void StockPlot::add_stock(QList& data_list, const QString& name)
96 | {
97 | if (m_name2series.contains(name))
98 | return;
99 |
100 | prepare_data(data_list);
101 |
102 | QCandlestickSeries* series = new QCandlestickSeries();
103 | series->setName(name);
104 | series->setIncreasingColor(QColor(Qt::green));
105 | series->setDecreasingColor(QColor(Qt::red));
106 |
107 | for (auto& item : data_list)
108 | {
109 | QCandlestickSet* set = new QCandlestickSet(item.m_timestamp);
110 | set->setProperty("parent", name);
111 | set->setOpen(item.m_open);
112 | set->setHigh(item.m_high);
113 | set->setLow(item.m_low);
114 | set->setClose(item.m_close);
115 | series->append(set);
116 | m_axisx_list << QDateTime::fromMSecsSinceEpoch(set->timestamp()).toString("dd");
117 | }
118 |
119 | m_chart->addSeries(series);
120 | m_name2series[name] = series;
121 | series->attachAxis(m_axisX);
122 | series->attachAxis(m_axisY);
123 | m_axisX->setCategories(m_axisx_list);
124 | m_axisY->setRange(m_min_y, m_max_y);
125 |
126 | connect(series, &QCandlestickSeries::hovered, this, &StockPlot::slot_tool_tip);
127 | //connect_markers();
128 | }
129 |
130 | void StockPlot::delete_stock(const QString& name)
131 | {
132 | if (!m_name2series.contains(name))
133 | return;
134 | m_chart->removeSeries(m_name2series[name]);
135 | m_name2series.remove(name);
136 |
137 | m_range[0].pop();
138 | m_range[1].pop();
139 | m_range[2].pop();
140 | m_range[3].pop();
141 |
142 | m_min_x = m_range[0].top();
143 | m_max_x = m_range[1].top();
144 | m_min_y = m_range[2].top();
145 | m_max_y = m_range[3].top();
146 |
147 | m_axisX->setRange(QString::number(m_min_x), QString::number(m_max_x));
148 | m_axisY->setRange(m_min_y * 0.99, m_max_y * 1.01);
149 | }
150 |
151 | void StockPlot::init_chart()
152 | {
153 | //m_chart->legend()->hide();
154 | }
155 |
156 | void StockPlot::init_axis()
157 | {
158 | m_axisX = new QBarCategoryAxis();
159 | m_chart->addAxis(m_axisX, Qt::AlignBottom);
160 |
161 | m_axisY = new QValueAxis();
162 | m_chart->addAxis(m_axisY, Qt::AlignLeft);
163 | }
164 |
165 | void StockPlot::init_series()
166 | {
167 | m_name2series.clear();
168 | }
169 |
170 | void StockPlot::prepare_data(QList& data_list)
171 | {
172 | for (auto& data : data_list)
173 | {
174 | if (data.m_timestamp < m_min_x)
175 | m_min_x = data.m_timestamp;
176 | if (data.m_timestamp > m_max_x)
177 | m_max_x = data.m_timestamp;
178 | if (data.m_low < m_min_y)
179 | m_min_y = data.m_low;
180 | if (data.m_high > m_max_y)
181 | m_max_y = data.m_high;
182 | }
183 | m_range[0].push(m_min_x);
184 | m_range[1].push(m_max_x);
185 | m_range[2].push(m_min_y);
186 | m_range[3].push(m_max_y);
187 | }
188 |
--------------------------------------------------------------------------------
/projects/Test/Test.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |