通用曲线控件源码定制之设计实现篇(功能丰富灵活) 浮云E绘图
曲线以图形表现数据,比表格数据直观多了,在各行业得到广泛的应用。浮云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 stub 29 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<Double> labels) { 77 draw(canvas, paint, plotArea, labels, 0); 78 } 79 80 public void draw(Canvas canvas, Paint paint, RectF plotArea, 81 List<Double> 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<Double> 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 + xPixelsPerUnit 105 * (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, orgY 118 + _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 = orgY 146 + _scaleFontStyle.size + _majorScaleLineLength 147 + _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<Double> 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 + xPixelsPerUnit 170 * (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<Double> 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 - yPixelsPerUnit 236 * (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<Double> 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 - yPixelsPerUnit 299 * (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<Double> 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<Double> 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<Double> 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版源码工程下载。
浙公网安备 33010602011771号