UE4练习 控件蓝图重载OnPaint画折线图
蓝图开发笔记,导入外部CSV文件结合UMG的重载OnPaint函数绘制折线图,数据关联一周七天温度变化
目录
前言
业余琢磨的笔记,将Excel数据另存csv文件导入UE4,不用插件用控件蓝图自带的重载Onpaint函数做个折线图看曲线变化。其实主要是通过练习了解一些好用的节点。总结:费劲,用js写个网页然后通过webBrowser插件填个URL或者python处理来的更快并且可以处理更大数据量
效果
csv文件的数据内容,包含 日期 以及当日 最高温 与 最低温

如果没有一个0下的温度,便不绘制0度线
文件准备

结构 Dfs_Excel 设置引擎内接收数据表格的结构
数据表格 Temp 导入CSV文件后生成的数据表格文件 行数据结构关联Dfs_Excel
Actor类蓝图 BP_WGManager 用于创建控件蓝图WG_Temp用
控件蓝图 WG_Temp 实现折线图效果用
控件蓝图 WGsub_Text 作为子控件加入WG_Temp控件蓝图中,用于显示文本
数据准备与导入
设置结构 Dfs_Excel

创建结构文件,或自己写个UStruct吧
导入csv文件
将拥有数据的csv文件拖入引擎中,列名对得上结构 Dfs_Excel 的设计
红框部分关联结构 当前文件为/Game/Temp才对(因为已经导入过了所以另创一个aaa.csv文件演示)
第一列总莫名弹出导入失败,只是列名对不上数据,但其实数据是进的来的,所以ID列数据全0了(悲,但不影响所以拉了个ID列顶一顶。效果如下
数据准备工作完成
创建三个工作蓝图类
BP_WGManager
这里如果在Gameplay框架中可以在pawn或者HUD管理中实现,图方便用个Actor类来创建控件蓝图。
仅做显示鼠标光标 GetPlayerController->show Mouse Cursor
解除鼠标晃动视角 解除控制
添加控件蓝图用 create Widget 以及 添加到视口 AddToViewpoint
WG_Temp与用作子控件的WGsub_Text
设计器部分的结构都是 本体->尺寸框SizeBox->画布面板CanvasPanel->(父控件加个可有可无的背景模糊;子控件加静态文本控件TextBlock)

可见加粗的都勾上IsVariable,会作为对象引用变量出现在蓝图中
WGsub_Text的配置
设计器部分操作
1、屏幕尺寸设为所需
2、尺寸框->细节 勾选 高度重载(40) 宽度重载(0)
3、静态文本块->细节->锚点改成全锚->偏移全改0
4、静态文本块->细节->外观->对齐->居中
5、静态文本块->细节->内容->文本->创建一个FString字符串类型的变量绑定
6、连连看部分
更新尺寸框的宽高重载 其中宽度重载关联绑定的字符串变量长度,每位*20个虚幻单位
WG_Temp配置
设计器部分
1、屏幕尺寸->自定义1600*900
2、尺寸框宽高重载关联屏幕尺寸 宽度重载(1600) 高度重载(900)
3、尺寸框下的画布面板全满做尺寸框子控件并勾上IsVariable用作接收后续的子控件
图表/蓝图部分
任务1 接收尺寸框大小
创建变量部分
AreaWidth 用作接收尺寸框宽度重载
AreaHeight 用作接收尺寸框高度重载
ChartWidth 用作接收尺寸框宽度重载0.8
ChartHeight 用作接收尺寸框高度重载0.8
连连看部分 
需要节点 尺寸框->GetWidthOverride/GetHeightOverride
任务2 获取Temp数据
创建变量部分
GetExcelDataTempHighest 映射 字符串与浮点 用于存储日期与对应的当日最高温度
GetExcelDataTempLowest 映射 字符串与浮点 用于存储日期与对应的当日最低温度
Array_Temp_Date 数组 字符串 用于存储日期
ExcelDataRowLenght 整型 用于存储计得行数
TemperatureMax 浮点 用于存储所有数据最高温
TemperatureMin 浮点 用于存储所有数据最低温
连连看部分
思路:获取数据 清空记录用的数据集 装入新数据
Clear节点 清除两个映射、日期字符串数组
行数归0
获取数据 读取Temp用节点
GetDataTableRowName 获取数据表行名称
GetDataTableRow{None} 获取数据表{None}行 在此None填入Temp
通过获取数据表的行名来循环,同时这个行名可以用来查询行数据,在通过中断节点获取数据
获取Temp数据完成
任务3 判断需不需要零线
创建变量部分
bIsNeedZeroLine 布尔 判断需不需要零线
连连看部分
如果最低温低于0则bIsNeedZeroLine为true
任务4 计算设计表格用的最高线与最低线
需求,为在纵轴画五格六线,且希望最高线与最低线是5的倍数
思路
创建变量部分
ModulusNumForTemp 整型 计算离最高温最近的5n用,为求表格最高线
ChartTopTempNum 整型 表格最高线温度值
ChartBottomTempNum 整型 表格最低线温度值
ModulusNumForChart 整型 分五格六线的纵轴步长
(五格六线,也即表格纵向分五格需要包括X轴在内共6线)
连连看部分
并非最优算法,举例当前数据中最高27度,那么为得出表格最高温度线30度,求27/5=5.4 加1等于6.4并截取得6,最后再乘以5得出表格需要的最高温度线
同理,在判断当前数据最低温是否低于0度之后,分情况更新表格需要的最低温度线值,如果存在低于0度的情况,将0下的最低温数值取绝对值进行上述算法,否则,默认最低温度线是0度线。
最后求五格六线中六线上的数值,先求纵轴步长
用表格最高线-最低线的差值来除以5得出每条线的步长ModulusNumForChart,如果为n格n+1线的需求则除以n
任务5 生成Y轴上示意的文本块
以任务4得出的数据数据设计子控件文本内容并添加到该控件中
无新变量
连连看部分
表格最高线与最低线插值除以表格步长得出循环次数为6,当然这是应对6线的特值情况
然后用最高线值 - (上图循环中的Index做倍数 * 步长) = 结果做6线上每条线的示意值并转为FString填入子控件暴露的字符串变量,同时字符串变量与文本内容绑定。
接下来调整子控件在父控件画布中的位置
在使用节点 AddChild添加子项 后
子控件->slot as Canvas slot 插槽为画布插槽->SetPosition设置位置 来调整子控件位置
具体位置计算算法如下
从左到右,我为表中预留的空间高度大概是0.7AreaHeight,所以以此为基础计算
坐标X = AreaWidth * 0.04
坐标Y = AreaHeight(0.2 + index * 0.7 / 6)
其中0.2是父控件画布顶部到表格最高线预留空间,0.7是表格预留高度,6是六线
循环完成后,判断是否需要画0线
求得0线在表格中由下至上的占比
0线占比 = float(Abs(表格最低线值))/float(表格最高线 - 表格最低线)
创建零线位置用的子控件 并依0线占比计算位置
坐标X = AreaWidth * 0.06 稍作区分此处乘以0.06
坐标Y = AreaHeight(0.2 + 0.7 * (1 - 0线占比))*
最终效果
生成如上图绿框中的六或七个文本框,并且有对应数值
任务6 生成X轴上示意的文本块

通过字符串数组Array_Temp_Date中记录的时间截取月/日创建子控件,年份也创建子控件放在下图绿框中的位置
处理FString自带一个Split分割节点,一般以查找到的第一个符号做分割
位置计算部分记录月/日文本框的算法
坐标X = AreaWidth * (0.15 + index * 0.1)
坐标Y = AreaHeight 0.92*
其中index是循环次数,其中0.15与0.1用作调整位置,整体不复杂
本任务目前仅考虑单年情况,如果有跨年数据还需要放置两个年份文本框位置的算法
OnPaint画线
任务1 画XY轴
控件蓝图->函数->重载->绘制时OnPaint

将Context提升为局部变量ThisPaint,因为后续会经常用到该对象引用
通过Context->绘制线条
作从左起0.1AreaWidth到0.9AreaWidth
高度在0.9AreaHeight的直线
同样作左侧0.1AreaWidth
上起0.1AreaHeight到0.9AreaHeight的直线
任务2 画平行于X轴的六线
由于六线包含X轴,其实只需要画五条线,所以下图绿框中-1,该案例只循环5次
并在之中嵌套一个循环用以画虚线
具体思路其实就是画的了直线就能把直线分成多段绘制成虚线
(但其实Context提供了一个画多组线的DrawLines可以创建二维向量组来画,但记得画完一条线后,在获取画下一条线的数据前清空数组)
如果有0下温度的情况,绘制0度线,算法与计算0度文本框一样,画线与画平行线思路一样。
同理结合0线的文本位置也可以以这个思路绘制0线位置,如果数据需要的话。
任务3 画温度变化折线
新增变量
PaintTempLine_PointA 二维向量 线头点
PaintTempLine_PointB 二维向量 线尾点
通过时间数组查询映射中对应时间的温度
(由于画当日高温与低温思路相同,仅使用不同映射,所以只记录高温线画法)

计算该温度在表中坐标并存取线尾点二维向量。
坐标X = AreaWidth * (0.175 + index * 0.1) 调整位置用的0.175与0.1
坐标Y = AreaHeight((1- ((查询结果温度-表格最低温)/(表格最高温-表格最低温)))0.7 + 0.2)
思路是计算查询结果与表格最低温的差值在表格最高温与最低温差值中的占比,此时是由下向上的占比,所以要用1减去该比例,再乘以 0.7个AreaHeight,其中0.2个AreaHeight是画布顶到表格顶的预留空间,简化后为上述公式。
进行画线判定
仅当线头与线尾两点都非(0,0)才画,画线如下
无论画不画都将线尾点赋值给线头点,这样就能绘制有N个有效点的n-1条线段
具体效果如下,可设置绘制线段颜色,以及点上的度数示意文本位置都可以用这个算法。
完成
这样就有了一个绘制折线图的模板,可以通过结合外部导入的CSV文件的数据实现,并且后续可调整Temp中的数据并保存就能更新图表。
具体记录一个绘制思路以及一些节点。
更多推荐




所有评论(0)