完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转stemwin教程
本期教程讲解STemWin支持的绘图控件。 45. 1 绘图件介绍 45. 2 官方WIDGET_GraphYT实例 45. 3 使用官方GUIBulder建立Graph控件 45. 4 总结 45.1 图形控件介绍 图形控件可用于可视化数据。图形控件的典型应用是显示测量值或函数图形的曲线,可同时显示多条曲线。可使用水平和垂直刻度来标记曲线。可在背景上显示具有不同水平和垂直间距的网格。如果数据阵列不能容纳进图形的可见区域,小工具可自动显示滚动条,从而可在大的数据阵列中进行滚动。 |
|
相关推荐
|
|
45.1.1 图形控件的结构
图形控件由不同种类的对象组成: l 图形控件自身,可以附加数据对象和刻度对象。 l 可选的一个或多个数据对象。 l 可选的一个或多个刻度对象。 下图显示了图形控件的详细结构: |
|
|
|
|
|
截图中每个参数表示的含义如下:
|
|
|
|
|
|
45.1.2 创建和删除图形小工具
创建图形控件的过程如下: l 创建图形控件并设置所需的属性。 l 创建数据对象。 l 将数据对象附加到图形控件。 l 创建可选的刻度对象。 l 将刻度对象附加到图形控件。 附加到图形控件后,就不需要通过应用程序来删除数据和刻度对象,而由图形控件完成。 示例 复制代码 GRAPH_DATA_Handle hData; GRAPH_SCALE_Handle hScale; WM_HWIN hGraph; hGraph = GRAPH_CreateEx(10, 10, 216, 106, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_GRAPH0); hData = GRAPH_DATA_YT_Create(GUI_DARKGREEN, NumDataItems, aData0, MaxNumDataItems); GRAPH_AttachData(hGraph, hData); hScale = GRAPH_SCALE_Create(28, GUI_TA_RIGHT, GRAPH_SCALE_CF_VERTICAL, 20); GRAPH_AttachScale(hGraph, hScale); /* Do something with the widget... */ WM_DeleteWindow(hGraph); |
|
|
|
|
|
45.1.3 绘制过程
如前所述,图形控件由不同部分和 “子”对象组成。以下描述了绘制控件的顺序: 1. 用背景色填充背景。 2. 调用可选的回调例程。例如,这样就能绘制用户定义的网格。 3. 绘制网格 (如已启用)。 4. 绘制数据对象和边框区域。 5. 绘制刻度对象。 6. 调用可选的回调例程。例如,这样就能绘制用户定义的刻度,或一些其他的文本和/或图形。 |
|
|
|
|
|
45.1.4 支持的曲线类型
显示测量值连续更新的曲线的要求不同于显示具有X/Y坐标的函数图形的要求。因此,控件当前支持2种数据对象,如下表所示: GRAPH_DATA_XY:此数据对象用于显示由点阵列组成的曲线,对象数据绘制为折线。此数据对象的典型应用是绘制函数图形。 GRAPH_DATA_YT:此数据对象用于显示图形上每个X位置都具有一个Y值的曲线。此数据对象的典型应用是显示测量值连续更新的曲线。 |
|
|
|
|
|
45.2 官方WIDGET_GraphYT实例
官方的这个实例很好的演示了GraphYT的使用,这个例子在模拟器中的位置: |
|
|
|
|
|
源码如下(程序中进行了详细的注释):
复制代码 ---------------------------------------------------------------------- File : WIDGET_Graph.c Purpose : Demonstrates the use of the GRAPH widget ---------------------------------------------------------------------- */ #include #include #include "DIALOG.h" #include "GRAPH.h" /********************************************************************* * * Defines * ********************************************************************** */ #define MAX_VALUE 180 /********************************************************************* * * Static data * ********************************************************************** */ static GRAPH_DATA_Handle _ahData[3]; /* 定义三种曲线的句柄 */ static GRAPH_SCALE_Handle _hScaleV; /* 垂直放缩的句柄 */ static GRAPH_SCALE_Handle _hScaleH; /* 水平放缩的句柄 */ static I16 _aValue[3]; static int _Stop; /* 三种曲线的显示颜色 */ static GUI_COLOR _aColor[] = {GUI_RED, GUI_GREEN, GUI_LIGHTBLUE}; /* 对话框资源 */ static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { { FRAMEWIN_CreateIndirect, "Graph widget demo", 0 , 0, 0, 320, 240, FRAMEWIN_CF_MOVEABLE }, { GRAPH_CreateIndirect, 0, GUI_ID_GRAPH0 , 5, 5, 270, 175 }, { TEXT_CreateIndirect, "Spacing X:", 0 , 10, 185, 50, 20 }, { TEXT_CreateIndirect, "Spacing Y:", 0 , 10, 205, 50, 20 }, { SLIDER_CreateIndirect, 0, GUI_ID_SLIDER0 , 60, 185, 60, 16 }, { SLIDER_CreateIndirect, 0, GUI_ID_SLIDER1 , 60, 205, 60, 16 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK0 , 130, 185, 50, 0 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK1 , 130, 205, 50, 0 }, { TEXT_CreateIndirect, "Border", 0 , 280, 5, 35, 15 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK2 , 280, 20, 35, 0 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK3 , 280, 40, 35, 0 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK4 , 280, 60, 35, 0 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK5 , 280, 80, 35, 0 }, { TEXT_CreateIndirect, "Effect", 0 , 280, 100, 35, 15 }, { RADIO_CreateIndirect, 0, GUI_ID_RADIO0 , 275, 115, 35, 0, 0, 3 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK6 , 180, 185, 50, 0 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK7 , 180, 205, 50, 0 }, { BUTTON_CreateIndirect, "Full Screen", GUI_ID_BUTTON0 , 235, 185, 65, 18 }, { CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK8 , 235, 205, 70, 0 }, }; /********************************************************************* * * _AddValues * */ static void _AddValues(WM_HWIN hGraph) { int i; int Add; int Vz; /* 通过for语句循环三次给三个数据对象_ahData[i]添加随机数数据 */ for (i = 0; i < GUI_COUNTOF(_aValue); i++) { Add = rand() % (2 + i * i); Vz = ((rand() % 2) << 1) - 1; _aValue[i] += Add * Vz; if (_aValue[i] > MAX_VALUE) { _aValue[i] = MAX_VALUE; } else if (_aValue[i] < 0) { _aValue[i] = 0; } /* 下面的这个函数用于把给定的数据值添加到数据对象。如果该数据对象 “已满”,即意味着它包含的数据项与创建时在参 数MaxNumItems中指定的项数相同,在添加新值前会首先移动一个数据项。因此,向 “已满”对象添加数据项时,第一 个数据项被移出。 */ GRAPH_DATA_YT_AddValue(_ahData[i], _aValue[i]); } } /********************************************************************* * * _UserDraw * * 本函数的目的: * 在绘制之前和绘制之后调用这个函数 ,此函数只是显示字母Temperature */ static void _UserDraw(WM_HWIN hWin, int Stage) { /* 在绘制之后被调用 */ if (Stage == GRAPH_DRAW_LAST) { char acText[] = "Temperature"; GUI_RECT Rect, RectInvalid; int FontSizeY; /* 设置字体 */ GUI_SetFont(&GUI_Font13_ASCII); FontSizeY = GUI_GetFontSizeY(); /* 得到矩形框的大小 */ WM_GetInsideRect(&Rect); /* Returns the invalid rectangle of a window in desktop coordinates */ WM_GetInvalidRect(hWin, &RectInvalid); Rect.x1 = Rect.x0 + FontSizeY; GUI_SetColor(GUI_RED); GUI_DispStringInRectEx(acText, &Rect, GUI_TA_HCENTER, strlen(acText), GUI_ROTATE_CCW); } } /********************************************************************* * * _ForEach * * 这个函数用于隐藏或者显示所有的窗口,除了button,graph和scroll控件 * */ static void _ForEach(WM_HWIN hWin, void * pData) { int Id, FullScreenMode; FullScreenMode = *(int *)pData; Id = WM_GetId(hWin); if ((Id == GUI_ID_GRAPH0) || (Id == GUI_ID_BUTTON0) || (Id == GUI_ID_VSCROLL) || (Id == GUI_ID_HSCROLL)) { return; } if (FullScreenMode) { WM_HideWindow(hWin); } else { WM_ShowWindow(hWin); } } /********************************************************************* * * _ToggleFullScreenMode * * 这个函数用于设置进入全屏模式与否,进入相应的模式以后需要放大或者缩小控件 */ static void _ToggleFullScreenMode(WM_HWIN hDlg) { static int FullScreenMode; static GUI_RECT Rect; static unsigned ScalePos; WM_HWIN hGraph, hButton; hGraph = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0); /* 取反 */ FullScreenMode ^= 1; /* 全屏模式 */ if (FullScreenMode) { /* 进入全屏模式 */ WM_HWIN hClient; GUI_RECT RectInside; hClient = WM_GetClientWindow(hDlg); BUTTON_SetText(hButton, "Back"); /* 相对移动*/ WM_MoveWindow(hButton, 0, 11); /* 隐藏标题 */ FRAMEWIN_SetTitleVis(hDlg, 0); /* 得到用户区的坐标 */ WM_GetInsideRectEx(hClient, &RectInside); /* 返回窗口大小 */ WM_GetWindowRectEx(hGraph, &Rect); /* 遍历所有的子控件,并且将其隐藏 */ WM_ForEachDesc(hClient, _ForEach, &FullScreenMode); /* Hide all descendants */ /* 设置窗口位置 */ WM_SetWindowPos(hGraph, WM_GetWindowOrgX(hClient), WM_GetWindowOrgX(hClient), RectInside.x1, RectInside.y1); /* 水平范围值,显示的位置 */ /* 返回的数值是以前的值 */ ScalePos = GRAPH_SCALE_SetPos(_hScaleH, RectInside.y1 - 20); } /* 进入正常模式 */ else { /* 返回到正常模式 */ BUTTON_SetText(hButton, "Full Screen"); WM_MoveWindow(hButton, 0, -11); WM_ForEachDesc(WM_GetClientWindow(hDlg), _ForEach, &FullScreenMode); /* Show all descendants */ WM_SetWindowPos(hGraph, Rect.x0, Rect.y0, Rect.x1 - Rect.x0 + 1, Rect.y1 - Rect.y0 + 1); FRAMEWIN_SetTitleVis(hDlg, 1); GRAPH_SCALE_SetPos(_hScaleH, ScalePos); } } /********************************************************************* * * _cbCallback * * 对话框回调函数 */ static void _cbCallback(WM_MESSAGE * pMsg) { int i, NCode, Id, Value; WM_HWIN hDlg, hItem; hDlg = pMsg->hWin; switch (pMsg->MsgId) { /* 初始化窗口消息 */ case WM_INIT_DIALOG: /* 得到相应的句柄 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); /* 创建三个数据对象_ahData[i] */ for (i = 0; i < GUI_COUNTOF(_aColor); i++) { _aValue[i] = rand() % 180; /* 创建成功的话,返回数据句柄 */ /* 显示的曲线颜色,可以显示的最大数据个数,数据指针,要添加的数据个数 */ _ahData[i] = GRAPH_DATA_YT_Create(_aColor[i], 500, 0, 0); /* 为绘图控件添加数据对象 */ GRAPH_AttachData(hItem, _ahData[i]); } /* 设置绘图属性 */ /* 设置垂直栅格的高度 */ GRAPH_SetGridDistY(hItem, 25); /* 栅格是否可见 */ GRAPH_SetGridVis(hItem, 1); /* 固定X轴的栅格 */ GRAPH_SetGridFixedX(hItem, 1); GRAPH_SetUserDraw(hItem, _UserDraw); /* 创建和增加垂直范围尺度标签 */ /* 离左边的尺度位置,*/ _hScaleV = GRAPH_SCALE_Create( 35, GUI_TA_RIGHT, GRAPH_SCALE_CF_VERTICAL, 35); /* 设置标签字体颜色 */ GRAPH_SCALE_SetTextColor(_hScaleV, GUI_RED); /* 将标签添加到垂直方向 */ GRAPH_AttachScale(hItem, _hScaleV); /* 创建和增加水平范围尺度标签 */ _hScaleH = GRAPH_SCALE_Create(155, GUI_TA_HCENTER, GRAPH_SCALE_CF_HORIZONTAL, 50); /* 设置字体颜色 */ GRAPH_SCALE_SetTextColor(_hScaleH, GUI_DARKGREEN); /* 添加到水平方向 */ GRAPH_AttachScale(hItem, _hScaleH); /* 下面的四个用来设置,上下左右四个边界 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK2); CHECKBOX_SetText(hItem, "L"); /* 注意,下面的函数将触发回调函数的执行 */ CHECKBOX_SetState(hItem, 1); /* 上边界 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK3); CHECKBOX_SetText(hItem, "T"); /* 右边界 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK4); CHECKBOX_SetText(hItem, "R"); /* 低边界 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK5); CHECKBOX_SetText(hItem, "B"); hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK0); CHECKBOX_SetText(hItem, "Stop"); hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK1); CHECKBOX_SetText(hItem, "Grid"); CHECKBOX_SetState(hItem, 1); hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK6); CHECKBOX_SetText(hItem, "HScroll"); CHECKBOX_SetState(hItem, 1); hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK7); CHECKBOX_SetText(hItem, "VScroll"); hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK8); CHECKBOX_SetText(hItem, "Left align"); /* 初始化滑动控件 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_SLIDER0); /* 设置范围 */ SLIDER_SetRange(hItem, 0, 10); /* 特别注意,设置了此函数的话,将自动的触发执行回调 */ SLIDER_SetValue(hItem, 5); /* tick的数目:没有实际的意义 */ SLIDER_SetNumTicks(hItem, 6); hItem = WM_GetDialogItem(hDlg, GUI_ID_SLIDER1); /* 设置范围 */ SLIDER_SetRange(hItem, 0, 20); SLIDER_SetValue(hItem, 5); /* tick的数目 */ SLIDER_SetNumTicks(hItem, 6); /* 初始化单选按钮控件 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_RADIO0); RADIO_SetText(hItem, "3D", 0); RADIO_SetText(hItem, "flat", 1); RADIO_SetText(hItem, "-", 2); /* 初始化按钮控件 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0); /* 保持一直在上层 */ WM_SetStayOnTop(hItem, 1); break; case WM_NOTIFY_PARENT: Id = WM_GetId(pMsg->hWinSrc); /* 控件ID*/ NCode = pMsg->Data.v; /* 通知代码 */ switch (NCode) { case WM_NOTIFICATION_CLICKED: switch (Id) { case GUI_ID_BUTTON0: /* 进入全屏模式 */ _ToggleFullScreenMode(hDlg); break; } break; case WM_NOTIFICATION_VALUE_CHANGED: switch (Id) { case GUI_ID_CHECK0: /* Toggle stop mode */ /* 翻转 */ _Stop ^= 1; break; case GUI_ID_CHECK1: /* 得到GRAPH0的句柄 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); /* 方格是否显示 */ GRAPH_SetGridVis(hItem, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK1))); break; case GUI_ID_CHECK2: case GUI_ID_CHECK3: case GUI_ID_CHECK4: case GUI_ID_CHECK5: /* 设置上下左右的坐标的边界值 */ /* 这里需要注意上面3个没有break */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); /* 设置上,下,左,右边界 */ GRAPH_SetBorder(hItem, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK2)) * 40, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK3)) * 5, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK4)) * 5, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK5)) * 5); break; case GUI_ID_SLIDER0: /* 设置水平方格间距 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); Value = SLIDER_GetValue(pMsg->hWinSrc) * 10; /* 设置方格的间距 */ GRAPH_SetGridDistX(hItem, Value); /* 设置tick的数值 也就是水平的坐标尺度 */ GRAPH_SCALE_SetTickDist(_hScaleH, Value); break; case GUI_ID_SLIDER1: /* 设置垂直方格间距 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); Value = SLIDER_GetValue(pMsg->hWinSrc) * 5; GRAPH_SetGridDistY(hItem, Value); /* 设置tick的数值 也就是垂直坐标的尺度 */ GRAPH_SCALE_SetTickDist(_hScaleV, Value); break; case GUI_ID_RADIO0: /* 设置空间效果 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); switch (RADIO_GetValue(pMsg->hWinSrc)) { case 0: WIDGET_SetEffect(hItem, &WIDGET_Effect_3D); break; case 1: WIDGET_SetEffect(hItem, &WIDGET_Effect_Simple); break; case 2: WIDGET_SetEffect(hItem, &WIDGET_Effect_None); break; } break; case GUI_ID_CHECK6: /* 由此来触发是否选择滚动条 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK6))) { /* 设置滚动条 */ GRAPH_SetVSizeX(hItem, 500); } else { /* 这里设置为0,就是相当于不再显示滚动条 */ GRAPH_SetVSizeX(hItem, 0); } break; case GUI_ID_CHECK7: /* 同上,这里是设置垂直的滚动条 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK7))) { GRAPH_SetVSizeY(hItem, 300); } else { GRAPH_SetVSizeY(hItem, 0); } break; case GUI_ID_CHECK8: /* 这里主要是设置对齐方式 */ hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); for (i = 0; i < GUI_COUNTOF(_aColor); i++) { if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK8))) { GRAPH_DATA_YT_SetAlign(_ahData[i], GRAPH_ALIGN_LEFT); } else { GRAPH_DATA_YT_SetAlign(_ahData[i], GRAPH_ALIGN_RIGHT); } } break; } break; } break; default: WM_DefaultProc(pMsg); } } /********************************************************************* * * Public code * ********************************************************************** */ /********************************************************************* * * MainTask */ void MainTask(void) { WM_HWIN hDlg, hGraph = 0,hGraph1 = 0; GUI_Init(); GUI_CURSOR_Show(); WM_SetDesktopColor(GUI_BLACK); #if GUI_SUPPORT_MEMDEV /* 所以的窗体自动的使用内存设备 */ WM_SetCreateFlags(WM_CF_MEMDEV); #endif /* 创建对话框 */ hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); while (1) { #ifdef WIN32 GUI_Delay(10); #endif /* 是否设置暂停 */ if (!_Stop) { /* 可以不需要这个,因为下面的添加数值函数没有使用这个句柄 */ if (!hGraph) { hGraph = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0); } /* 这里是在添加数值 */ _AddValues(hGraph); } GUI_Exec(); } } |
|
|
|
|
|
45.3 使用官方GUIBulder建立Graph控件
使用官方提供的GUIBulder5.22也可以建立Graph控件,但是不完善,只能将其添加到窗口上,下面的截图就是用GUIBulder5.22设计的。 |
|
|
|
|
|
设置后的显示效果如下:
现在GUIBuder5.22仅支持这些功能。大家有兴趣的可以在这个的基础上面建立一个Graph控件并在模拟器或者开发板上显示出来。 |
|
|
|
|
|
45.4 总结
本期教程主要是跟大家讲解了绘图控件的使用,希望大家可以把本期教程中讲的这个例子跑跑,然后自己设计一个相关的例子进行试验学习。教程中只是使用了部分的绘图控件API,其它的API大家都可以试试。 官方还有一个WIDGET_GraphXY的实例,大家可以研究下。 |
|
|
|
|
|
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-使用AHT20进行环境监测之AHT20传感器介绍
203 浏览 0 评论
761 浏览 0 评论
806 浏览 1 评论
基于瑞萨FPB-RA4E2智能床头灯项目——1编译环境搭建与点亮驱动ws2812全彩LED
743 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
1195 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11806 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 16:17 , Processed in 1.970123 second(s), Total 95, Slave 77 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号