【WinForm UI控件系列】散点图/折线图控件 (支持数值型、时间型、字符串型)

前言:c# winform UI控件系列(Net6+),纯GDI绘图无依赖,虽然做不到最好,争取做好更好用!

一、效果图 (x轴三种类型:数值、时间、字符串)





  • 支持五种颜色风格。
  • 标题:位置支持(左中右布局)
  • x轴标题、y轴标题:支持旋转角度。图例支持位置定义(选择合适位置)
  • 是否显示连线,是否显示网格线,是否圆滑曲线

二、使用说明

ScatterPlot 散点图/折线图控件

控件简介

ScatterPlot 是一个功能强大的散点图和折线图控件,参考 ScottPlot 设计,支持平滑曲线、多种X轴类型(数值型、字符串型、日期时间型)、网格线、值提示和图例显示。

主要特性

  • 多种X轴类型:支持 Numeric(数值)、Category(字符串类别)、DateTime(日期时间)
  • 平滑曲线:支持 Smooth 平滑曲线显示,可调整张力
  • 网格线:支持 X/Y 轴网格线显示控制
  • 值提示:鼠标悬停显示数据点值,支持自动格式化
  • 图例位置控制:支持 7 种图例位置(None, TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight)
  • 轴标签旋转:支持 X/Y 轴标签旋转角度设置
  • 自动日期时间格式:根据时间跨度自动选择最优显示格式
  • 属性变更通知:实现 INotifyPropertyChanged,属性值改变立即生效

基本使用

简单散点图

csharp 复制代码
// 创建散点图控件
var scatterPlot = new ScatterPlot
{
    Dock = DockStyle.Fill,
    ColorType = ColorType.Primary
};

// 添加数据系列
var series = new ScatterSeries
{
    Name = "系列1",
    ShowLine = true,
    ShowMarkers = true,
    Smooth = true
};

// 添加数据点
for (int i = 0; i < 10; i++)
{
    series.Points.Add(new ScatterPoint(i, Math.Sin(i * 0.5) * 10 + 20));
}

scatterPlot.Series.Add(series);
scatterPlot.RefreshPlot();
this.Controls.Add(scatterPlot);

X轴类型设置

csharp 复制代码
// 数值型(默认)
scatterPlot.XAxisType = XAxisType.Numeric;

// 字符串类别型
scatterPlot.XAxisType = XAxisType.Category;

// 日期时间型
scatterPlot.XAxisType = XAxisType.DateTime;

日期时间型数据

当使用 XAxisType.DateTime 时,控件会自动根据时间跨度选择合适的显示格式:

时间跨度 X轴显示格式 Tooltip格式
≤24小时 HH:mm HH:mm
≤72小时 MM-dd HH:mm MM-dd HH:mm
≤30天 MM-dd MM-dd
≤1年 yyyy-MM yyyy-MM
>1年 yyyy-MM-dd yyyy-MM-dd
csharp 复制代码
// 日期时间型示例(24小时内数据)
scatterPlot.XAxisType = XAxisType.DateTime;
scatterPlot.Title = "24小时温度变化";
scatterPlot.XAxisLabel = "时间";

var series = new ScatterSeries
{
    Name = "今日温度",
    ShowLine = true,
    ShowMarkers = true
};

// 添加24小时内的数据点
DateTime today = DateTime.Now.Date;
series.Add(today.AddHours(0), 18);
series.Add(today.AddHours(6), 20);
series.Add(today.AddHours(12), 28);
series.Add(today.AddHours(18), 24);
series.Add(today.AddHours(24), 19);

scatterPlot.AddSeries(series);
scatterPlot.RefreshPlot();

图例位置控制

csharp 复制代码
scatterPlot.ShowLegend = true;
scatterPlot.LegendPosition = LegendPosition.TopRight;  // 右上角
scatterPlot.LegendOrientation = LegendOrientation.Horizontal;  // 水平排列

轴标签旋转

csharp 复制代码
// X轴标签旋转 45 度
scatterPlot.AxisLabelStyle.XAxisRotation = 45;

// Y轴标签旋转 -90 度
scatterPlot.AxisLabelStyle.YAxisRotation = -90;

网格线控制

csharp 复制代码
// 显示 X 轴网格线
scatterPlot.GridLineStyle.ShowX = true;

// 显示 Y 轴网格线
scatterPlot.GridLineStyle.ShowY = true;

// 设置网格线颜色
scatterPlot.GridLineStyle.Color = Color.FromArgb(230, 230, 230);

属性说明

主要属性

属性名 类型 默认值 说明
Series List - 数据系列集合
XAxisType XAxisType Numeric X轴类型
ColorType ColorType Primary 色彩类型
Title string "" 图表标题
XAxisLabel string "" X轴标题
YAxisLabel string "" Y轴标题

图例属性

属性名 类型 默认值 说明
ShowLegend bool true 是否显示图例
LegendPosition LegendPosition BottomCenter 图例位置
LegendOrientation LegendOrientation Horizontal 图例排列方向

轴标签样式

属性名 类型 默认值 说明
AxisLabelStyle.XAxisRotation int 0 X轴标签旋转角度
AxisLabelStyle.YAxisRotation int 0 Y轴标签旋转角度
AxisLabelStyle.FontSize float 9 标签字体大小
AxisLabelStyle.Color Color Gray 标签颜色

网格线样式

属性名 类型 默认值 说明
GridLineStyle.ShowX bool true 是否显示X轴网格线
GridLineStyle.ShowY bool true 是否显示Y轴网格线
GridLineStyle.Color Color LightGray 网格线颜色
GridLineStyle.Width int 1 网格线宽度

事件

PointClicked

数据点点击事件,可用于显示详细信息:

csharp 复制代码
scatterPlot.PointClicked += (sender, args) =>
{
    string xValue;
    if (scatterPlot.XAxisType == XAxisType.DateTime)
    {
        xValue = new DateTime((long)args.Point.X).ToString("MM-dd HH:mm");
    }
    else
    {
        xValue = args.Point.X.ToString();
    }
    
    MessageBox.Show($"系列: {args.Series.Name}\nX: {xValue}\nY: {args.Point.Y:F2}");
};

完整示例

24小时温度变化

csharp 复制代码
var scatterPlot = new ScatterPlot
{
    Dock = DockStyle.Fill,
    Title = "24小时温度变化",
    XAxisLabel = "时间",
    YAxisLabel = "温度 (°C)",
    XAxisType = XAxisType.DateTime,
    ShowLegend = true,
    LegendPosition = LegendPosition.BottomCenter
};

// 今日温度
var todaySeries = new ScatterSeries
{
    Name = "今日温度",
    LegendText = "今日",
    ShowLine = true,
    ShowMarkers = true,
    Smooth = true,
    SmoothTension = 0.4f,
    LineWidth = 2
};

DateTime today = DateTime.Now.Date;
todaySeries.Add(today.AddHours(0), 18);
todaySeries.Add(today.AddHours(2), 17);
todaySeries.Add(today.AddHours(4), 16);
todaySeries.Add(today.AddHours(6), 17);
todaySeries.Add(today.AddHours(8), 20);
todaySeries.Add(today.AddHours(10), 24);
todaySeries.Add(today.AddHours(12), 28);
todaySeries.Add(today.AddHours(14), 30);
todaySeries.Add(today.AddHours(16), 29);
todaySeries.Add(today.AddHours(18), 26);
todaySeries.Add(today.AddHours(20), 23);
todaySeries.Add(today.AddHours(22), 20);
todaySeries.Add(today.AddHours(24), 19);

scatterPlot.AddSeries(todaySeries);
scatterPlot.RefreshPlot();
this.Controls.Add(scatterPlot);

多日期温度对比

csharp 复制代码
var scatterPlot = new ScatterPlot
{
    Dock = DockStyle.Fill,
    Title = "温度趋势图",
    XAxisLabel = "日期",
    YAxisLabel = "温度 (°C)",
    XAxisType = XAxisType.DateTime,
    ShowLegend = true,
    LegendPosition = LegendPosition.TopRight
};

// 本周温度
var series1 = new ScatterSeries
{
    Name = "本周温度",
    LegendText = "本周",
    ShowLine = true,
    ShowMarkers = true,
    Smooth = true,
    LineWidth = 2
};

// 添加7天数据
for (int i = -6; i <= 0; i++)
{
    series1.Add(DateTime.Now.AddDays(i).Date, 20 + Math.Sin(i * 0.5) * 5);
}

scatterPlot.AddSeries(series1);
scatterPlot.RefreshPlot();

注意事项

  1. 日期时间数据 :使用 DateTime.ToOADate()DateTime.Ticks 转换为数值存储
  2. 刷新图表 :修改数据后调用 RefreshPlot() 重新绘制
  3. 平滑曲线 :设置 Smooth = true 并可通过 SmoothTension 调整平滑度(0-1之间)
  4. 图例绘制:图例始终在最上层显示,不会被网格线遮挡
  5. 轴标题 :设置 XAxisLabelYAxisLabel 会自动预留空间,避免与轴标签重叠

三、后记

陆续补充完善中,敬请关注,如有需求,有好的建议,请留言(xue5zhijing)

相关推荐
ZC跨境爬虫19 分钟前
跟着 MDN 学 HTML day_53:(深入理解 XPathResult 接口)
前端·javascript·ui·html·音视频
tedcloud1236 小时前
UI-TARS-desktop部署教程:构建AI桌面自动化系统
服务器·前端·人工智能·ui·自动化·github
ZC跨境爬虫10 小时前
跟着MDN学HTML_day_48:(Node接口)
前端·javascript·ui·html·音视频
为何创造硅基生物11 小时前
嵌入式 LVGL / SquareLine UI 标准命名规则(行业通用版)
windows·ui
AITOP10019 小时前
高德联合千问开源AGenUI:让Agent UI同时跑在iOS、安卓和鸿蒙上
ui·ios·开源
UXbot1 天前
AI原型设计工具如何从PRD自动生成交互原型
前端·低代码·ui·交互·ai编程·原型模式
十五年专注C++开发1 天前
QFluentKit: 一个基于 Qt Widgets 的 Fluent Design 风格 UI 组件库
开发语言·c++·qt·ui·qfluentkit
ZC跨境爬虫1 天前
跟着MDN学HTML_day_47:(Document接口)
前端·javascript·ui·html·ecmascript·音视频
Ulyanov1 天前
《从质点到位姿:基于Python与PyVista的导弹制导控制全栈仿真》: 基石——3-DOF质点弹道的高保真建模与数值稳定性分析
开发语言·python·算法·ui·系统仿真
ZC跨境爬虫1 天前
跟着MDN学HTML_day_49:(ShadowRoot接口)
前端·javascript·ui·html·ecmascript·媒体