曲线以图形表现数据,比表格数据直观多了,在各行业得到广泛的应用。浮云E绘图长期从事工业控制和军工软件研发,擅长绘图编辑器、曲线控件等软件研发,本文开启通用曲线控件的设计到编码实现系列文章。

通用曲线,即曲线功能较丰富,可以灵活满足常用曲线支持。本系列文章针对通用曲线控件做实现,下一个系列讲针对基于时间的海量数据曲线高效实现。


(相关资料图)

一、曲线控件部件介绍

曲线控件一般如上图所示,包含以下部件:

0.控件描述:曲线控件区域大小、背景颜色等。支持曲线实时测量、缩放、翻页、导出打印等。

1.标题Title:标题文本内容、字体类型、字体大小、字体颜色。标题区域大小、区域背景色、区域内文字对齐(左中右上下)、文字排列角度(横/竖/斜角)、标题区域基于曲线方位(上下左右/内嵌)、是否显示。

2.网格Grid:网格向类型(横向/纵向)、网格线类型(主/次线)、是否显示(主次线)、线粗细、线型(虚实)、线颜色。

3.曲线轴(X轴和Y轴):轴向类型(X/Y)、轴主副类型(X1/X2、Y1/Y2)、轴数据类型(线性轴/指数/时间/文本轴)、轴名称(文字内容、字体颜色、字型、字号、文字对齐、文字排列),轴线(线宽、线颜色、线型、端线类型(无/实心箭头/箭头线))。实现支持双X轴、双Y轴。

4.曲线:曲线类型(线性曲线/阶梯/散点/柱状/区域曲线)、曲线颜色、线条粗细、是否标注Marker(标注类型、颜色、宽度等)、曲线数据集。

曲线数据与轴类型有对应关系。一般Y轴都是数值轴,而X轴可能是数值、时间、文本等轴。当X是时间轴、Y是数值轴时,曲线点数据格式应该时x是时间值、y是数值。

5.图例Legend:图例列表排列方式(横/纵向)、图例区域块(区域大小、背景色)、图例基于控件的方位(上下左右/内嵌)、是否显示。

图例与曲线是一一对应关系,风格类型也是一致,这样才能直观的示例。比如曲线控件有2条曲线,A曲线是红色线条+方块标注,B曲线是蓝色柱状曲线,那么图例应该也是2个,A曲线图例一条线中间+方块图例,B曲线图例蓝色方块。

6.(脚注FootNote):与标题Title类似,有的曲线需要底部一段文字备注说明,或者实时显示轴移动中的原点值。

二、通用曲线控件灵活功能支持

如果定制的曲线控件应用场景单一,就没必要实现过多用不到的功能细节(比如标题文字多种排列和布局);如果想定制开发一套比较通用的曲线控件源码,那么就需要兼顾多种情况。

1. 坐标轴数据类型:较常用的包含线性轴 / 指数轴 / 时间轴 / 文本轴

2. 曲线类型:较常用的包含线性曲线 / 阶梯曲线 / 散点曲线 / 柱状曲线 / 饼状占比等

3. 坐标轴主副类型:同时支持X主轴X1、X副轴X2和Y主轴X1、Y副轴X2。至少一对X和Y即可。(一般不会用多轴展示数据,对比反而不直观。多数据对比曲线,一般采用,多区域纵向排列(X-Y1,X-Y2,X-Y3...)X轴同步的方式实现,请等待下一个系列曲线详细说明。)

三、通用曲线控件源码软件结构设计

曲线控件功能结构图如下所示,画布View作为曲线呈现,Chart作为数据管理容​

根据上面功能结构,设计主要类:

1. 画布类:ChartView和SimpleView,ChartView作为通用画布,支持丰富XY多坐标系,而SimpleView实现为最简单的绘图接口,默认一些参数,使用简单。

public ChartView(AbstractChart chart) 

2.数据管理类:AbstractChart --> XY坐标系的XYChart 和 饼状图的RoundChart。

1 // 作者:浮云绘图,擅长工控、军工等领域绘图编辑器、曲线控件定制研发 2 // 联系:QQ 316868127 3  4 public XYChart(AbstractAxis axisX, AbstractAxis axisY,AbstractAxis axisX2, AbstractAxis axisY2) 5 public XYChart(AbstractAxis axisX, AbstractAxis axisY, null, null) 6  7  8 public void draw(Canvas canvas, Paint paint) 9 {10         canvas.save();11         canvas.clipRect(_clientArea);12         super.calcChartArea(paint);13 14         // 背景15         super.drawBackground(canvas, paint);16 17         // 轴、网格18         drawAxis(canvas, paint);19 20         // 曲线、图例、标题21         super.draw(canvas, paint);22         canvas.restore();23 }24 25 26 @Override protected void drawSeries(Canvas canvas, Paint paint) 27 {28     // TODO Auto-generated method stub29     for (int i = 0; i < _series.size(); i++) {30         AbstractSeries ser = _series.get(i);31         ser.drawLine(canvas, paint,_plotArea);32     }33 }34 35 36 @Override protected void scroll(EnZoomOrientation orientation, double physicsOffset)37 @Override protected void zoom(EnZoomOrientation orientation, PointD physicsCenter, double physicsScale)

3. 头部Header

1 public class Header extends TextNote { 2     private EnHeadPosition _position = EnHeadPosition.TopCenter; 3      4      5     public Header(String title, AbstractChart parent) { 6         super(title, parent); 7     } 8     public void draw(Canvas canvas, Paint paint){ 9         super.draw(canvas, paint);10     }11     12     public void setPosition(EnHeadPosition position){13         if(_position != position){14             _position = position;15             _parent.calcChartArea();        16         }17     }18     public EnHeadPosition getPosition(){19         return _position;20     }21     22     public enum EnHeadPosition{23         TopCenter,24         BottomCenter,25         LeftCenter,26     }27 }28 29 public class TextNote {30     protected AbstractChart _parent;31     protected boolean _visible = true;32     protected String _title = "Header title";33     protected FontStyle _fontStyle = new FontStyle(12, Color.BLACK);34     35     protected int _backColor = Color.LTGRAY;36     protected RectF _rectF = new RectF();37     protected boolean _isBoxShow = false;38     protected LineStyle _boxStyle = new LineStyle(1, Color.BLUE);39     40     private int _paddingInV = 2;        41     private int _paddingInH = 4;        42     43     public TextNote(String title, AbstractChart parent){44         this._title = title;45         _parent = parent;46     }47     public void draw(Canvas canvas, Paint paint){48         if (!_visible) {49             return;50         }51         52         paint.setStyle(Style.FILL);53         paint.setColor(_fontStyle.color);54         paint.setTextSize(_fontStyle.size);55         Rect r = new Rect();56         paint.getTextBounds(_title, 0, _title.length(), r);57         58 59         paint.setStyle(Style.FILL);60         paint.setColor(_backColor);61         canvas.drawRect(_rectF, paint);62         63 64         float x = 0F, y = 0F;65         x = _rectF.left + (_rectF.width() - r.width()) / 2 ;66         y = _rectF.top + (_rectF.height() - r.height()) / 2  + r.height() - 1.5f;67 68         paint.setTextSize(_fontStyle.size);69         paint.setColor(_fontStyle.color);70         canvas.drawText(_title, x, y, paint);71 72 73         if (_isBoxShow) {74             paint.setStyle(Style.STROKE);75             paint.setColor(_boxStyle.color);76             paint.setStrokeWidth(_boxStyle.width);77             canvas.drawRect(_rectF, paint);78         }79     }80 81 ......82 }

4. 网格Grid

1 public class Grid {2     private EnGridType _type = EnGridType.X;3     private boolean _visible = true;4     private LineStyle _majorGridLineStyle;5     private LineStyle _minorGridLineStyle;6 ......7 8 }

5.坐标轴:AbstractAxis --> 线性轴LinearAxis、指数轴LogAxis、时间轴DatetimeAxis 、文本轴LabelAxis。

1 // 作者:浮云绘图  2 // 联系:QQ 316868127  3   4 public abstract class AbstractAxis {  5     public enum EnAxisType // 坐标轴类型  6     {  7         X, // 主X轴  8         Y, // 主Y轴  9         X2, // 副X轴 10         Y2, // 副Y轴 11         All, // 所有轴 12     }; 13  14     public enum EnAxisTitleAlign // 轴名称文字位置 15     { 16         Center, // 居中 17         Away, // 轴最大值方向对齐 18         Near, // 轴最小值方向对齐 19     }; 20  21     public enum EnTickerMode { // 刻度线模式 22         Above, // 轴上 23         Underside, // 轴下 24         Both, // 轴上下 25     }; 26  27  28     protected EnAxisType _type; 29     protected boolean _visible = false; 30 //    protected boolean _reversed = false; 31 //    protected boolean _autoScale = true; 32     protected double _dMax; // 最大值 33     protected double _dMin; // 最小值 34 //    protected double _dMajor; // 大刻度间隔 35     protected double _origin = Double.MAX_VALUE; // XY轴起点 36     protected boolean _autoOrigin = true; 37  38     // 标题--abcd 39     private int k = 3432;    //svn tst 40     protected String _title = "Axis"; 41     protected FontStyle _titleFontStyle; 42 //    protected EnAxisTitleAlign _titleAlign; 43     protected boolean _titleVisible = true; 44  45     // 轴线 46     protected LineStyle _axisLineStyle; 47  48     // 刻度线 49     protected LineStyle _scaleLineStyle; 50     protected int _majorScaleLineLength = 5; // 大刻度线长 51     protected int _scaleLabelToValueLength = 2; 52     protected boolean _showTickMarks = true ; 53  54     // 刻度值 55     protected float _scaleValeAngle; 56     protected FontStyle _scaleFontStyle; 57     protected int _scaleValueColor = Color.BLACK; 58     protected boolean _showLabels = true; 59  60     // 网格 61     protected Grid _grid; 62  63     protected AbstractAxis() { 64         _dMax = Double.MIN_VALUE; 65         _dMin = Double.MAX_VALUE; 66  67         _titleFontStyle = new FontStyle(11, Color.BLACK); 68         _axisLineStyle = new LineStyle(1, Color.BLACK); 69         _scaleLineStyle = new LineStyle(1, Color.BLACK); 70         _scaleFontStyle = new FontStyle(10, Color.CYAN); 71  72         _grid = new Grid(); 73     } 74  75     public void draw(Canvas canvas, Paint paint, RectF plotArea, 76             List labels) { 77         draw(canvas, paint, plotArea, labels, 0); 78     } 79  80     public void draw(Canvas canvas, Paint paint, RectF plotArea, 81             List labels, float originOffset) { 82         if (!_visible) { 83             return; 84         } 85  86         Rect txtRect = new Rect(); 87         String txtLable = ""; 88         float position = 0; 89          90         paint.setStyle(Style.FILL); 91         switch (_type) { 92         case X: { 93             double xPixelsPerUnit = plotArea.width() 94                     / (WorldToPhysical(_dMax) - WorldToPhysical(_dMin)); 95  96             // 网格 刻度线 标签 轴线 名称 97             List axisLabels = labels; 98             boolean showGridY = _grid.getVisible(); 99             float orgY = plotArea.bottom - originOffset;100             int length = axisLabels.size();101 102             for (int i = 0; i < length; i++) {103                 double label = axisLabels.get(i);104                 float xLabel = (float) (plotArea.left + xPixelsPerUnit105                         * (WorldToPhysical(label) - WorldToPhysical(_dMin)));106 107                 paint.setStyle(Style.STROKE);108                 if (showGridY) {109                     paint.setStrokeWidth(_grid.getMarjorGridLineStyle().width);110                     paint.setColor(_grid.getMarjorGridLineStyle().color);111                     canvas.drawLine(xLabel, plotArea.bottom, xLabel,112                             plotArea.top, paint);113                 }114                 if (_showTickMarks) {115                     paint.setStrokeWidth(_scaleLineStyle.width);116                     paint.setColor(_scaleLineStyle.color);117                     canvas.drawLine(xLabel, orgY, xLabel, orgY118                             + _majorScaleLineLength, paint);119                 }120                 if (_showLabels) {121                     paint.setStyle(Style.FILL);122                     paint.setColor(_scaleValueColor);123                     paint.setTextSize(_scaleFontStyle.size);124                     txtLable = getValueFormat(label);125                     paint.getTextBounds(txtLable, 0, txtLable.length(), txtRect);126                     127                     position = orgY + _scaleFontStyle.size + _majorScaleLineLength + _scaleLabelToValueLength;128                     if (!_showTickMarks) {129                         position -= _majorScaleLineLength/* + _scaleLabelToValueLength*/;130                     }131                     132                     canvas.drawText(txtLable, xLabel - txtRect.width() / 2, position, paint);133                 }134             }135             paint.setStyle(Style.STROKE);136             paint.setColor(_axisLineStyle.color);137             paint.setStrokeWidth(_axisLineStyle.width);138             canvas.drawLine(plotArea.left, orgY, plotArea.right, orgY, paint);139 140             paint.setStyle(Style.FILL);141             paint.setColor(_titleFontStyle.color);142             paint.setTextSize(_titleFontStyle.size);143 144             Rect rect = GraphUtil.getBounds(paint, _title);145             position = orgY146                     + _scaleFontStyle.size + _majorScaleLineLength147                     + _scaleLabelToValueLength + _titleFontStyle.size;148             if (!_showTickMarks) {149                 position -= _majorScaleLineLength/* + _scaleLabelToValueLength*/;150             }151             if (!_showLabels){152                 position -= _scaleFontStyle.size;153             }154             canvas.drawText(_title, plotArea.right - rect.width() - 5, position, paint);155         }156             break;157         case X2: {158             double xPixelsPerUnit = plotArea.width()159                     / (WorldToPhysical(_dMax) - WorldToPhysical(_dMin));160 161             // 网格 刻度线 标签 轴线 名称162             List axisLabels = labels;163             boolean showGridY = _grid.getVisible();164             float orgY = plotArea.top;165             int length = axisLabels.size();166 167             for (int i = 0; i < length; i++) {168                 double label = axisLabels.get(i);169                 float xLabel = (float) (plotArea.left + xPixelsPerUnit170                         * (WorldToPhysical(label) - WorldToPhysical(_dMin)));171 172                 paint.setStyle(Style.STROKE);173                 if (showGridY) {174                     paint.setStrokeWidth(_grid.getMarjorGridLineStyle().width);175                     paint.setColor(_grid.getMarjorGridLineStyle().color);176                     canvas.drawLine(xLabel, plotArea.bottom, xLabel,177                             plotArea.top, paint);178                 }179                 if (_showTickMarks) {180                     paint.setStrokeWidth(_scaleLineStyle.width);181                     paint.setColor(_scaleLineStyle.color);182                     canvas.drawLine(xLabel, orgY - _majorScaleLineLength,183                             xLabel, orgY, paint);184                 }185                 if (_showLabels) {186                     paint.setStyle(Style.FILL);187                     paint.setColor(_scaleValueColor);188                     paint.setTextSize(_scaleFontStyle.size);189                     txtLable = getValueFormat(label);190                     paint.getTextBounds(txtLable, 0, txtLable.length(), txtRect);191                     192                     position = orgY - _majorScaleLineLength- _scaleLabelToValueLength;193                     if (!_showTickMarks) {194                         position += _majorScaleLineLength/* + _scaleLabelToValueLength*/;195                     }196                     197                     canvas.drawText(txtLable, xLabel - txtRect.width() / 2, position, paint);198                 }199             }200             paint.setStyle(Style.STROKE);201             paint.setColor(_axisLineStyle.color);202             paint.setStrokeWidth(_axisLineStyle.width);203             canvas.drawLine(plotArea.left, orgY, plotArea.right, orgY, paint);204 205             paint.setStyle(Style.FILL);206             paint.setColor(_titleFontStyle.color);207             paint.setTextSize(_titleFontStyle.size);208             Rect rect = GraphUtil.getBounds(paint, _title);209             210             position = orgY - _scaleFontStyle.size - _majorScaleLineLength - _scaleLabelToValueLength;211             if (!_showTickMarks) {212                 position += _majorScaleLineLength/* + _scaleLabelToValueLength*/;213             }214             if (!_showLabels){215                 position += _scaleFontStyle.size;216             }217             218             canvas.drawText(_title, plotArea.right - rect.width() - 5, position, paint);219 220         }221             break;222 223         case Y: {224             double yPixelsPerUnit = plotArea.height()225                     / (WorldToPhysical(_dMax) - WorldToPhysical(_dMin));226 227             // 网格 刻度线 轴线 标签 名称228             List axisLabels = labels;229             boolean showGridX = _grid.getVisible();230             float orgX = plotArea.left + originOffset;231             int length = axisLabels.size();232 233             for (int i = 0; i < length; i++) {234                 double label = axisLabels.get(i);235                 float yLabel = (float) (plotArea.bottom - yPixelsPerUnit236                         * (WorldToPhysical(label) - WorldToPhysical(_dMin)));237 238                 paint.setStyle(Style.STROKE);239                 if (showGridX) {240                     paint.setStrokeWidth(_grid.getMarjorGridLineStyle().width);241                     paint.setColor(_grid.getMarjorGridLineStyle().color);242                     canvas.drawLine(plotArea.left, yLabel, plotArea.right,243                             yLabel, paint);244                 }245                 if (_showTickMarks) {246                     paint.setStrokeWidth(_scaleLineStyle.width);247                     paint.setColor(_scaleLineStyle.color);248                     canvas.drawLine(orgX - _majorScaleLineLength, yLabel, orgX,249                             yLabel, paint);250                 }251                 if (_showLabels) {252                     paint.setStyle(Style.FILL);253                     paint.setColor(_scaleValueColor);254                     paint.setTextSize(_scaleFontStyle.size);255                     txtLable = getValueFormat(label);256                     paint.getTextBounds(txtLable, 0, txtLable.length(), txtRect);257                     258                     position = orgX - txtRect.width() - _majorScaleLineLength - _scaleLabelToValueLength;259                     if (!_showTickMarks) {260                         position += _majorScaleLineLength/* + _scaleLabelToValueLength*/;261                     }262                     canvas.drawText(txtLable, position, yLabel + _scaleFontStyle.size / 2, paint);263                 }264             }265             paint.setStyle(Style.STROKE);266             paint.setColor(_axisLineStyle.color);267             paint.setStrokeWidth(_axisLineStyle.width);268             canvas.drawLine(orgX, plotArea.top, orgX, plotArea.bottom, paint);269 270             paint.setStyle(Style.FILL);271             paint.setColor(_titleFontStyle.color);272             paint.setTextSize(_titleFontStyle.size);273             Rect rect = GraphUtil.getBounds(paint, _title);274             int scaleVMaxWidth = getLablesMaxLength(paint, labels);275             276             position = orgX - scaleVMaxWidth - _majorScaleLineLength - _scaleLabelToValueLength - 2;277             if (!_showTickMarks) {278                 position += _majorScaleLineLength/* + _scaleLabelToValueLength*/;279             }280             if (!_showLabels){281                 position += scaleVMaxWidth;282             }283             GraphUtil.drawText(canvas, _title, position, plotArea.top + rect.width() + 5, paint, -90);284         }285             break;286         case Y2: {287             double yPixelsPerUnit = plotArea.height()288                     / (WorldToPhysical(_dMax) - WorldToPhysical(_dMin));289 290             // 网格 刻度线 轴线 标签 名称291             List axisLabels = labels;292             boolean showGridX = _grid.getVisible();293             float orgX = plotArea.right;294             int length = axisLabels.size();295 296             for (int i = 0; i < length; i++) {297                 double label = axisLabels.get(i);298                 float yLabel = (float) (plotArea.bottom - yPixelsPerUnit299                         * (WorldToPhysical(label) - WorldToPhysical(_dMin)));300 301                 paint.setStyle(Style.STROKE);302                 if (showGridX) {303                     paint.setStrokeWidth(_grid.getMarjorGridLineStyle().width);304                     paint.setColor(_grid.getMarjorGridLineStyle().color);305                     canvas.drawLine(plotArea.left, yLabel, plotArea.right,306                             yLabel, paint);307                 }308                 if (_showTickMarks) {309                     paint.setStrokeWidth(_scaleLineStyle.width);310                     paint.setColor(_scaleLineStyle.color);311                     canvas.drawLine(orgX, yLabel, orgX + _majorScaleLineLength,312                             yLabel, paint);313                 }314                 if (_showLabels) {315                     paint.setStyle(Style.FILL);316                     paint.setColor(_scaleValueColor);317                     paint.setTextSize(_scaleFontStyle.size);318                     txtLable = getValueFormat(label);319                     paint.getTextBounds(txtLable, 0, txtLable.length(), txtRect);320                     321                     position = orgX + _majorScaleLineLength + _scaleLabelToValueLength;322                     if (!_showTickMarks) {323                         position -= _majorScaleLineLength/* + _scaleLabelToValueLength*/;324                     }325                     canvas.drawText(txtLable, position, yLabel + _scaleFontStyle.size / 2, paint);326                 }327             }328             paint.setStyle(Style.STROKE);329             paint.setColor(_axisLineStyle.color);330             paint.setStrokeWidth(_axisLineStyle.width);331             canvas.drawLine(orgX, plotArea.top, orgX, plotArea.bottom, paint);332 333             paint.setStyle(Style.FILL);334             paint.setColor(_titleFontStyle.color);335 //            Rect rect = GraphUtil.getBounds(paint, _title);336             int scaleVMaxWidth = getLablesMaxLength(paint, labels);337             338             position = orgX + scaleVMaxWidth + _majorScaleLineLength + _scaleLabelToValueLength + 2;339             if (!_showTickMarks) {340                 position -= _majorScaleLineLength/* + _scaleLabelToValueLength*/;341             }342             if (!_showLabels){343                 position -= scaleVMaxWidth;344             }345             GraphUtil.drawText(canvas, _title, position, plotArea.top + 5, paint, 90);346         }347             break;348         default:349             break;350         }351     }352 353     public int getAxisOutLength(Paint paint, List labels) {354         // 轴名称文本、刻度值文本、刻度线355         int outLength = 0;356         Rect rect = new Rect();357 358         if (_type == EnAxisType.X || _type == EnAxisType.X2) {359             if (_titleVisible) {360                 paint.getTextBounds(_title, 0, _title.length(), rect);361                 outLength += 1 + rect.height();362             }363             if (_showLabels) {364                 outLength += 1 + _scaleFontStyle.size;    //getLablesMaxLength(paint, labels)365             }366             if (_showTickMarks) {367                 outLength += _scaleLabelToValueLength + _majorScaleLineLength;368             }369         } else if (_type == EnAxisType.Y || _type == EnAxisType.Y2) {370             if (_titleVisible) {371                 paint.getTextBounds(_title, 0, _title.length(), rect);372                 outLength += 1 + rect.height(); // 轴文本逆时针转90度,否则改成rect.width()373             }374             if (_showLabels) {375                 outLength += 1 + getLablesMaxLength(paint, labels);376             }377             if (_showTickMarks) {378                 outLength += _scaleLabelToValueLength + _majorScaleLineLength;379             }380         }381         return outLength;382     }383 384     private int getLablesMaxLength(Paint paint, List labels) {385         int len = 0;386         for (int i = 0; i < labels.size(); i++) {387             double label = labels.get(i);388             String s = getValueFormat(label);389 390             paint.setTextSize(_scaleFontStyle.size);391             Rect r = new Rect();392             paint.getTextBounds(s, 0, s.length(), r);393 394             if (len < r.width()) {395                 len = r.width();396             }397         }398         return len;399     }400     401     public void setVisible(boolean visible) {402         _visible = visible;403     }404 405     public boolean getVisible() {406         return _visible;407     }408 409     public void setType(EnAxisType type) {410         _type = type;411         if (type == EnAxisType.X || type == EnAxisType.X2) {412             _grid.setType(EnGridType.X);413         } else {414             _grid.setType(EnGridType.Y);415         }416     }417 418     public EnAxisType getType() {419         return _type;420     }421 422     public void setTitle(String name) {423         _title = name;424     }425 426     public String getTitle() {427         return _title;428     }429 430     public void setMax(double max) {431         _dMax = max;432     }433 434     public double getMax() {435         return _dMax;436     }437 438     public void setMin(double min) {439         _dMin = min;440         if (_autoOrigin) {441 //            if (_origin > _dMin) {442                 _origin = _dMin;443 //            }444         }445     }446 447     public double getMin() {448         return _dMin;449     }450 451     public void setOrigin(double origin) {452         _origin = origin;453         if (!_autoOrigin) {454             if (_origin < _dMin) {455                 _dMin = _origin;456             }457             if (_origin > _dMax) {458                 _dMax = _origin;459             }460         }461     }462 463     public double getOrigin() {464         return _origin;465     }466 467     public void setAutoOrigin(boolean autoOrigin) {468         _autoOrigin = autoOrigin;469     }470 471     public Grid getGrid() {472         return _grid;473     }474 475     public void setRange(double max, double min) {476         _dMax = max;477         _dMin = min;478     }479 480     public abstract List getLabels(double start, double end,481             int approxNumLabels);482 483     public abstract double[] getRealData(Object object);484 485     public abstract double WorldToPhysical(double val);486 487     public abstract String getValueFormat(double val);488 489     protected boolean IsAvailPoint(double val){490         if (val < _dMin || val > _dMax) {491             return false;492         }493         return true;494     }495 496 }

6.曲线类:AbstractSeries --> 线性曲线LineSeries、阶梯曲线StepSeries、散点曲线ScattSeries、柱状曲线BarSeries、饼状曲线PieSeries。

浮云E绘图的通用曲线控件源码定制之设计实现篇就写这么多,该曲线控件功能丰富,扩展性强,有java版和C++版本,功能下一篇文章将继续写用曲线控件源码定制重点和难点,并将提供Java版源码工程下载。

推荐内容