PBIDEA:用 uo_chart 画出柱状图与饼图
PBIDEA:用 uo_chart 画出柱状图与饼图阅读说明
1. 适用版本:PB 9 及以上(本文按 PB 12.5 + PBIDEA 1.x 验证;涉及 painter.pbl 与 websuite.pbl 两个库)
2. 支持数据库:无需数据库(示例全部使用内存 DataStore,不连接任何 DBMS)
3. 操作系统与环境要求:Windows 7+,已安装 PBIDEA 运行库(PbIdea.dll 等);应用库需包含 painter.pbl、websuite.pbl
4. 难度系数:★★☆☆☆
5. 其它阅读说明:前置知识为 DataStore 基本操作(InsertRow/SetItem);建议先看 Day 7《PBIDEA:uo_database 连接池与多库事务复用》了解 PBIDEA 库的引入方式
一、uo_chart 是什么
PBIDEA 的 painter.pbl 里放着一个自绘图表控件 uo_chart。它不依赖任何第三方 ActiveX/OCX,本质是一个 UserObject,通过 ue_paint 事件用 GDI 把图表直接画在窗口上,底层由 websuite.pbl 的 uo_painter(封装 PbIdea.dll)提供画板能力。
它内置 11 种图表类型,通过属性 is_charttype 切换:
is_charttype图表is_charttype图表
line折线图npie南丁格尔玫瑰图
bar柱状图percent百分比环形图
area面积图scatter散点图
pie饼图(可环形)radar雷达图
barline柱线混合guage仪表盘
h_bar横向柱状图
控件创建(constructor)时自动执行 uf_init():创建内部画板 uo_painter p、注册画布事件、并在程序目录建 chart 文件夹,不需要你手动初始化。
二、喂数据:uf_setdata(DataStore)
uo_chart 只有一个主要的数据入口——把 DataStore 传给它:调用 uo_chart_1.uf_setdata(ids) 返回 boolean,数据为空(RowCount < 1 或列数 < 1)时返回 false。
数据约定很关键,务必按这个结构准备 DataStore:
[*]第 1 列:每行的分组名(柱状图横轴上的组名、图例名);
[*]第 2 列起:数值系列。系列名取数据窗口里该列的列头文本,命名规则是"列名 + 下划线 t",例如列名 c1,列头文本控件就叫 c1_t(painter.pbl 自带的 d_chart_demo 就是这么命名的:c1_t 文本为"周一"、"c2_t"为"周二"……);
[*]数据为空(RowCount < 1 或列数 < 1)时返回 false。
柱状图多行多列 = 多组 × 多系列(自动堆叠);饼图一行多列 = 每个数值列一个扇区,扇区名取各列列头文本。
三、示例 1:窗口内画柱状图
前置:① 应用库列表已加入 painter.pbl、websuite.pbl;② 窗口 w_chart_demo 上放一个 UserObject 控件,命名为 uo_chart_1,对象类型选 uo_chart;③ 使用 painter.pbl 自带的数据窗口 d_chart_demo(列:legend + c1~c7,列头周一~周日)。
步骤:1) 打开窗口;2) 在按钮 cb_bar 的 clicked 事件贴入下方代码;3) 运行并点击按钮,即可看到两组 × 七个工作日的堆叠柱状图。
// ===== 示例输入:两周销售数据(第 1 列=分组名,第 2~8 列=周一~周日)=====
datastore ids
ids = create datastore
ids.DataObject = 'd_chart_demo' // painter.pbl 自带示例数据窗口
// 第一组:本店
ids.InsertRow(0)
ids.SetItem(1, 'legend', '本店')
ids.SetItem(1, 'c1', 12) // 周一
ids.SetItem(1, 'c2', 18) // 周二
ids.SetItem(1, 'c3', 15) // 周三
ids.SetItem(1, 'c4', 22) // 周四
ids.SetItem(1, 'c5', 19) // 周五
ids.SetItem(1, 'c6', 26) // 周六
ids.SetItem(1, 'c7', 14) // 周日
// 第二组:分店
ids.InsertRow(0)
ids.SetItem(2, 'legend', '分店')
ids.SetItem(2, 'c1', 9)
ids.SetItem(2, 'c2', 14)
ids.SetItem(2, 'c3', 12)
ids.SetItem(2, 'c4', 17)
ids.SetItem(2, 'c5', 16)
ids.SetItem(2, 'c6', 20)
ids.SetItem(2, 'c7', 11)
// ===== 配置图表外观 =====
uo_chart_1.is_charttype = 'bar' // 柱状图
uo_chart_1.is_title = '一周销售额对比' // 主标题
uo_chart_1.is_title1 = '(单位:千元)' // 副标题
uo_chart_1.ib_show_dzz = false // 关闭右下角水印
uo_chart_1.il_colorstyle = 3 // 色板 3(雅致),可选 1~14
// ===== 喂数据 + 重绘 =====
uo_chart_1.uf_setdata(ids)
uo_chart_1.uf_refresh() // 立即重绘到窗口
destroy ids
MessageBox('完成', '柱状图已绘制:2 组 × 7 个工作日')
四、示例 2:饼图(一行多列)
饼图的数据结构和柱状图不同:一行数据,第 2 列起每个数值列对应一个扇区,扇区名取各列列头文本。这里仍借用 d_chart_demo 演示(扇区名会显示为"周一~周四",想显示产品名,把数据窗口对应列的标题文本改成产品名即可)。
前置:同示例 1。步骤:在按钮 cb_pie 的 clicked 事件贴入下方代码,运行后点击按钮。
// ===== 示例输入:四个产品的销量占比(一行,第 1 列占位,第 2~5 列为四个扇区值)=====
datastore ids
ids = create datastore
ids.DataObject = 'd_chart_demo'
ids.InsertRow(0)
ids.SetItem(1, 'legend', '产品') // 占位,饼图用不到
ids.SetItem(1, 'c1', 45) // 扇区 1(列头"周一")
ids.SetItem(1, 'c2', 25) // 扇区 2
ids.SetItem(1, 'c3', 18) // 扇区 3
ids.SetItem(1, 'c4', 12) // 扇区 4
// c5~c7 留空即 0,不参与
// ===== 配置 =====
uo_chart_1.is_charttype = 'pie' // 饼图
uo_chart_1.is_title = '产品销量占比'
uo_chart_1.ib_link = false // false=实心饼;true=环形图
uo_chart_1.ib_show_dzz = false
// ===== 喂数据 + 重绘 =====
uo_chart_1.uf_setdata(ids)
uo_chart_1.uf_refresh()
destroy ids
MessageBox('完成', '饼图已绘制:4 个扇区')
五、示例 3:不依赖界面直接导出 PNG(报表出图)
做报表时经常要把图存成图片文件塞进导出文档里。uf_makechart() 可以脱离屏幕绘制:在内存画布上画完直接 SaveMemoryImage 存成文件,扩展名决定格式(png/jpg/bmp 均可)。调用前必须先 uf_setdata 喂过数据。
前置:同示例 1(窗口上需有 uo_chart_1 控件,因为对象实例化后才能创建内部画板)。步骤:在按钮 cb_export 的 clicked 事件贴入代码;先点"画柱状图"喂数据,再点本按钮。
integer li_rc
// ===== 示例输入:导出尺寸与文件路径 =====
integer li_w
integer li_h
string ls_file
li_w = 900
li_h = 520
ls_file = 'chart/sales_bar.png' // 相对程序运行目录;chart 目录由 uf_init 自动创建
li_rc = uo_chart_1.uf_makechart(li_w, li_h, ls_file)
if li_rc = 0 and FileExists(ls_file) then
MessageBox('导出成功', '图片已保存:' + ls_file)
else
MessageBox('导出失败', '返回码:' + string(li_rc))
end if
六、可选:点击图表取数据
控件内置两个点击事件,可用来做"点击柱/扇区弹出明细"的交互:
事件参数含义
ue_on_barai_row, ai_column点击柱子:第几组、第几列
ue_on_pieai_index点击扇区:第几个扇区
前置:窗口上已有 uo_chart_1。步骤:在 uo_chart_1 的事件列表里找到 ue_on_bar,双击进入并写入下方代码。
// uo_chart_1 的 ue_on_bar 事件:点击柱子时触发
MessageBox('点击了柱子', '第 ' + string(ai_row) + ' 组,第 ' + string(ai_column) + ' 列')
七、常见坑
[*]系列名取不到:数据窗口的列头文本控件必须命名为"列名_t"(如 c1 配 c1_t),否则取列头失败会回退成列名显示;
[*]饼图画不出多个扇区:饼图要用"一行多列",扇区数 = 数值列数;用了多行数据会被最后一行覆盖;
[*]图是空的:uf_setdata 返回 false 说明 DataStore 无数据或列数不足,先检查 RowCount 和列数;
[*]改完数据不刷新:喂数据后必须调 uf_refresh() 才会重绘;
[*]scatter / percent / guage 特殊:散点图用数组版 uf_setdata(ad_x[], ad_y[]);percent/guage 可用 uf_setdata(ad_v[], as_legend[]),其余类型都走 DataStore 版;
[*]水印与配色:ib_show_dzz 关闭水印;il_colorstyle 1~14 切换色板;柱状图 ib_stack=false 可取消堆叠、ib_3dbar=true 可开 3D。
小结
uo_chart 的核心用法只有三步:准备 DataStore(注意列头命名)→ uf_setdata 喂数据 → uf_refresh 重绘;需要图片文件时再用 uf_makechart 导出。理解了"第 1 列分组名、第 2 列起数值系列"这个约定,柱状图、饼图、折线图、雷达图等 11 种图基本都能照葫芦画瓢。下一篇继续讲 PBIDEA 的办公组件:用 uo_xlsx 读写 Excel。
页:
[1]