| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 深入浅出CChart 每日一课——快乐高四第五十六课 絮絮叨叨,岁月杀猪刀之FAQ -> 正文阅读 |
|
[C++知识库]深入浅出CChart 每日一课——快乐高四第五十六课 絮絮叨叨,岁月杀猪刀之FAQ |
CChart发布已有多年,QQ交流群也成立了很久。在和网友的交流中,发行了CChart的很多问题,也进行了很多改进和完善。 网友们接触CChart的时间有早有晚,不同的网友经常在群里或私聊的时候提出的相近的问题,本节课准备对这些共性问题进行一些介绍。 A56.1 刷新问题问:为什么我添加数据或修改数据后,屏幕的图像没有变化,或者是需要鼠标在图像上动一下图像才有变化? 答:CChart一般不会自动画图。 有时候你觉得好像我没有主动调用绘图函数啊,怎么也画图了呢?这是由于你使用CChartWnd的时候,在窗口的OnPaint函数里面调用了CChart的OnDraw函数。只要不触发OnPaint,图像是画不出来的。而鼠标移动有可能会触发OnPaint,所以有时候需要鼠标在图像上动一下图像才有变化。 为了主动刷新图像,在添加完数据后,可以调用一下CChartWnd::ReDraw(),或者CChart::OnDraw(HWND hWnd),也可以用Win32API的InvalidateRect刷新。 A56.2 默认背景问题问:我不喜欢CChart的默认背景,请问怎么取消? 答:一般软件都有一个无法取消的默认背景,起到版权宣示或者产品推广的作用, CChart的默认背景就温柔得多了,如下: 这个背景并不是强制性的,可以取消,也可以换成别的背景。参考本系列教程的第A17课,“深入浅出CChart 每日一课——快乐高四第十七课 麦田的守望,默认界面的设置方法_baita96的博客-CSDN博客”。 默认背景界面的设置内容其实也是很丰富的。 A56.3?多线程问题问:我在多线程下使用CChart,偶尔程序崩溃,但也不一定崩溃,是什么原因。 答:所有的操作系统,刷新UI界面都不建议在工作线程中进行,包括Windows、Linux、Android、MacOS等。因为各大系统的UI元素都不是线程安全的。 Windows推荐的在线程中刷新界面的标准方法是发消息,具体的方法是调用InvalidateRect,使得窗口某一部分失效,这样Windows系统会在主线程的消息队列里插入一个WM_PAINT消息,从而刷新窗口。当然,这样的话,由于WM_PAINT消息在队列里排队,有时候刷新可能不即时,可以在InvalidateRect之后,立马调用一下UpdateWindow或RedrawWindow,这样系统会立马处理WM_PAINT消息。 具体到CChart中,有两种情况。 如果使用的是CChart这个类,一般情况下在主线程里面可以调用OnDraw(HWND hWnd)这个接口刷新界面。但在主线程之外的其它线程里面,不要这样使用,还是用InvalidateRect吧。当然如果是MFC,可以调用Invalidate这个函数,它是InvalidateRect的一个包装。 如果使用的是CChartWnd,那么CChartWnd::ReDraw()这个接口就是刷新绘图区域。但这里要注意CChart::SetDirectRedraw(bool bRedraw)这个函数。默认情况下这个函数是设置为false的,也就是说,CChartWnd内部不是直接绘图,而是调用消息刷新的,也就是说这是安全的。如果SetDirectRedraw(true),那么CChartWnd内部调用OnDraw重绘,线程不安全。 A56.4?曲线颜色问题问:我怎么才能设置曲线的颜色,SetDataColor似乎不起作用? 答:CChart的曲线颜色具有很丰富的选项,具体设置方法请参考上一课“深入浅出CChart 每日一课——快乐高四第五十五课 天然去雕饰,出水芙蓉之美轮美奂_baita96的博客-CSDN博客”。 此外,上一课主要介绍的是绘图类型为kTypeXY的折线图的曲线颜色设置。对于多层视图,包括分层视图和共享X轴视图,默认情况下,每一层的所有曲线颜色均设置为和该层的坐标轴颜色相同,以便区分不同的图层。在这种情况下,如果想单独设置曲线颜色,请先调用CChart::SetUniteLayerColor(bool bUnite)这个接口,参数设置为false,以解除曲线颜色的绑定。 A56.5 曲线名称问题问:怎么修改屏幕上“未命名000”、“未命名001”等显示的曲线名称为我想要的名字? 答:屏幕上曲线名称是显示在图例之中的。每条曲线都有一个名称,可以用CChart::SetDataTitle()这个接口设置。如果不设置,在图例中显示的名称就是“未命名XXX”。 A56.6 图像缩放问题问:图像怎么放大缩小?可以用鼠标滚轮缩放图像吗? 答:在默认状态下,CChart是关闭图像缩放功能的。 打开图像缩放功能用两种方式。 一种是在程序运行时,通过右键菜单打开,“绘图状态”-->“特别功能”-->“坐标缩放”。 一种是通过代码打开,调用CChart::SetRangeZoomMode(); CChart坐标缩放功能是按住鼠标左键,往右拖动放大,往左拖动缩小(还原上一次拖动状态),很方便实用。 如图,在往右拖动的时候,会出现一个拖动框,松开鼠标左键,图像就放大到拖动框的范围。? 此外,打开坐标缩放功能后,默认鼠标滚轮就可以缩放图像了。 A56.7 图像显示范围问题问:图像默认的坐标轴范围和我想要的不一样,我想设置一下,但调用SetXRange或SetYRange后,根本没有任何作用,请问怎么办? 答:调用SetXRange、SetYRange或SetPlotRange后,不起作用的原因是CChart默认情况下是自动计算坐标轴显示范围的。为了让这些设置其作用,需要先调用一下SetXAutoRange(false)或SetYAutoRange(false)。 这里还有一个问题,如果图像中增加了曲线或某曲线增加了数据点,即使调用了SetXAutoRange或SetYAutoRange,显示范围也会重新计算。 为了彻底固定显示范围,可以调用SetXStaticRange(true)或SetYStaticRange(true)。 A56.8?数据点驱动的等高线图、云图、三维曲面图问题问:我已有一些数据点,怎么绘制等高线图、云图、三维曲面图? 答:CChart的等高线图、云图、三维曲面图,都是由场函数驱动的。场函数的基本形式是h=f(x,y),需要调用SetFieldFcn(f)以设置场函数。 如果已知一些数据点,怎么画图呢?理论上,可以根据这些数据点编写自己的场函数,然后SetFieldFcn即可。 但实际上,根据数据点获得场函数是一项难度极大的工作,这也是一个庞大的研究课题,用户自己实现的可能性极小。 CChart内部已经集成了多种算法,包括克里金法、自然邻域法、反距离权重法等。 具体的使用方法是需要先调用一下下面这个函数
CChart内部就建立了一个插值函数作为场函数,默认的插值算法是自然领域法。 然后添加数据点即可。添加数据点的接口为
详细的用法请参考本教程第A6课“深入浅出CChart 每日一课——快乐高四第六课 二丫的青梅,返璞归真之普通窗口多区域绘图_baita96的博客-CSDN博客”。 A56.9 同一个窗口绘制多个图像问题问:我想在一个窗口上画多个图像,请问怎么办? 答:单个窗口分成多个区域,然后每个区域画一张图像,这在CChart库中有多种实现方式。 方式1、利用分裂视图。 分裂视图直接将窗口客户区分成多块,每个区域绘制一个图像。 分裂视图划分窗口的方式有很多种,最简单的是按行列划分,也可以按左一右二、左二右一、上一下二、上二下一的方式划分,比较灵活。 详细的使用方式见本教程第十课“深入浅出CChart 每日一课——第十课 分裂视图,锤子肖哥之错位人格_baita96的博客-CSDN博客”。 分裂视图最大的优点是Chart内部对这种视图进行了一下处理,可以实现一些自己处理较难实现的功能,比如各个区域之间可以用鼠标拖动调整大小,Ctrl+鼠标双击可以切换单区域独占窗口功能等。 分裂视图也有一些问题,最大的问题是发布的版本里面,分开的每个区域都只能绘制折线图,不能画其它类型的图像,更不用说每个区域画不同类型图像了。 方式2、利用多个CChart类对象。 这种方式是设置多个CChart类对象,每一个对应窗口的一个区域。 本系列教程的A06、A07、A08三课都是讲述这个方式,详见“深入浅出CChart 每日一课——快乐高四第六课 二丫的青梅,返璞归真之普通窗口多区域绘图_baita96的博客-CSDN博客”、“深入浅出CChart 每日一课——快乐高四第七课 铁蛋的竹马,返璞归真之对话框窗口多区域绘图_baita96的博客-CSDN博客”、“深入浅出CChart 每日一课——快乐高四第八课 懵懂的童年,返璞归真之Duilib窗口多区域绘图_baita96的博客-CSDN博客_duilib多窗口”。 采用多个CChart类对象的方法,比较灵活。缺点是需要自己编写消息响应代码。当然如果不需要消息响应的话,这种方法是最好的。 方式3、利用多个ChartCtrl控件。 这种方式是在窗口每个区域放置一个ChartCtrl控件。 ChartCtrl控件是CChart内部已经注册的窗口类,可以看作和Windows内置的Button、Edit、Label等窗口类是等同的。 详细用法参见本系列教程的A15课,“深入浅出CChart 每日一课——快乐高四第十五课 罗马通途,利用ChartCtrl控件实现多区域绘图_baita96的博客-CSDN博客_chartctrl”。 此方法最关键的是一个函数: CChart *GetChart(HWND hWnd); 用这个函数获得CChart指针,然后进行各种操作。 其中hWnd这个句柄是ChartCtrl控件的窗口,如果不是的话,GetChart将返回空指针。 方式4、利用多个CChartWnd变量。 这种方式是窗口每个区域对应一个CChartWnd变量,Attach的时候,注意要给出该区域的RECT。 此方法的关键函数是: int CChartWnd::Attach(HWND hWnd, RECT rect); 注意最好不同区域的RECT不要有重叠的部分,以避免不必要的问题。 另一个关键函数是: CChart *CChartWnd::GetChart(); 这个函数获得CChart指针,然后就可以开展各种操作了。 注意这个函数没有形参。 方式5、利用单个CChartWnd变量,多次Attach 与上一个方式的差别在于,只有一个CChartWnd变量。CChart库已经实现了同一个CChartWnd多次Attach的功能,用户可以放心使用。 此方法的关键函数仍然是: int CChartWnd::Attach(HWND hWnd, RECT rect); 同样,Attach的时候,rect之间最好不要有重叠。 但是,可能同学们会疑惑,那怎么区分不同的图像呢?那就看看下面这个关键函数。 CChart *CChartWnd::GetChart(int nChartIndex); 真的吗?这个和上面那个方法不是同样的函数吗? 的确,还是上面那个函数,但这里带了形参。nChartIndex是图像序号。简单地说:第一次Attach的图像,其序号为0;第二次Attach的图像,其序号为1;以此类推。 方式6、前两种方式混用。 也就是说,可以设置多个CChartWnd变量,其中一些CChartWnd变量对应单个图像,另一些CChartWnd变量对应多个图像。 CChart库非常灵活,这样用是完全没有问题的。 A56.10 时间坐标轴问题问:我想让X轴显示为时间,请问怎么办? 答:CChart支持时间坐标轴,把一个坐标轴设置为时间轴的接口如下。
其中location表示哪个坐标轴,具体来说,0是左轴,1是下轴,2是右轴,3是上轴。 也可以设置时间刻度的显示格式。
注意这里的format格式字符串,这个字符串格式和C语言标准函数strftime是完全一样的,可以查阅strftime的资料。其中一部分,%Y表示年份,%m表示月份,%d表示日,%H表示小时,%M表示分,%S表示秒。 但是要注意,光把坐标轴设置为时间轴,数据也得是时间才对。 CChart内部的时间数据采用C语言的标准类型time_t数据。对于VC来说,time_t就是一个64位长整数, 也就是说,如果需要X轴显示时间,您的数据的X坐标应该是time_t数据。 数据输入的时候,可以直接给time_t数据,也可以利用时间字符串输入。相关的函数有
这两个函数的x数据由字符串给定,其中字符串的格式由fmt格式字符串指定,这个格式仍然需要参考strftime这个API。例如,假定时间是2022年6月20日16点50分30秒,时间字符串可以是”2022-06-20 16:50:30”,格式字符串为”%Y-%m-%d %H:%M:%S”,当然格式也可以调整。 注意,这里用于输入的字符串格式,可以和上面坐标轴显示的格式不一样。 当然,您也可以不用上面两个函数输入数据,仍然把时间数据用time_t直接输入。 不过,自己操作time_t可能比较困难,笨笨提供了一个时间字符串转数值的接口。
这里返回值就是time_t,但是转换为double了。 问:X轴显示为时间时,各个刻度的数据比较乱,比如显示多少分多少秒,我想让它稍微凑整一点可以吗? 答:这是可以的,可以利用下面这两个函数:
这两个函数的参数就表示刻度之间的间隔。对于time_t数据,就是多少秒。比如,您希望刻度间隔为5分钟,可以调用SetXAtom(300)。 当然,这个函数在内部实现的时候,不是硬性的。如果您设置的atom离实际情况差别比较大,这个函数不起作用。例如比如您的坐标总的范围只有1分钟,但您这里仍然设置atom为300,那明显超出太多。 问:X轴显示为时间时,时间精度能优于秒吗? 答:CChart的时间精度不能直接优于秒,但笨笨加了一些补丁,可以让时间精度优于秒。 CChart的时间精度不能直接优于秒的原因是内部采用time_t作为时间数据,time_t的最小只能表示到秒,不能再小。 当然,Windows系统提供的另一种时间数据COleTime,其精度完全可以优于秒,但CChart一开始就没有选择这种方案。 为了让时间精度优于秒。笨笨在CChart内部做了如下处理。 首先设置一个基准时间;然后具体的时间数据都是在基准时间的基础上变化,变化的精度当然是可以优于秒的;最后在绘制坐标轴的时候,显示坐标刻度时加上精确的秒数。 相关的接口如下:
此接口需要在SetAxisToTime之后调用,表示坐标轴是混合模式。
此接口表示混合模式的时候,小数部分的显示格式。 注意这里的format格式字符串不是参考strftime,而是参考printf这个最基本的函数。
此接口设置时间基准。 在混合模式下,数据点的输入时最好用StringToTime这个接口获得基准时间的数值,然后再加上相应的时间偏离,作为数据值。 A56.11?对数坐标轴问题问:我想让X轴显示对数刻度,请问可以吗? 答:CChart支持对数坐标轴,只需要调用这个接口即可。
当然,设置为对数坐标轴的前提是该坐标轴的所有数据都是正数,没有0或负数,不然会发生不可预计的错误。 A56.12 坐标轴反向问题问:我想让X轴从大到小显示,请问可以吗? 答:CChart默认情况下坐标轴数据都是从小到大显示的。 CChart支持坐标轴反向,只需要调用这个接口即可。
A56.13 坐标轴浮动刻度问题问:matlab等很多软件,其坐标轴刻度显示似乎和CChart不一样,这是怎么回事? 答:CChart在默认情况下,坐标轴的两端是有刻度的,并且刻度值是在一定程度上进行了“凑整”处理。其实大部分软件似乎都是这样处理的,只是凑整的算法不一样。 还有很多软件,包括matlab,采用了另外一种方法。这种是坐标轴的两端不一定有刻度线,刻度线是在坐标轴的内部比较“靠整”的位置显示。例如,假定坐标范围是0.5到5.5,其刻度线分别位于1、2、3、4、5这5个位置,起点和终点没有刻度线。 CChart实际上也支持这种刻度显示方式,并把这种方式称为“浮动刻度”模式,相应的接口如下:
A56.14 控制台程序问题问:CChart可以在Dos程序中使用吗? 答:所谓Dos程序,在Windows中称为控制台。 CChart是一个基于Win32API的软件库,纯粹的Dos程序,CChart是不支持的。但目前应该很难找到纯粹的Dos环境。 在Windows环境里面,CChart完美支持控制台程序。 实际上,在控制台程序里,既可以弹出一个Windows窗口,用于CChart绘图,也可以让CChart直接在控制台那个黑乎乎的窗口里绘图。 本系列教程里面,有多课内容都是讲述控制台编程的,包括A33课“深入浅出CChart 每日一课——快乐高四第三十三课 叶落归根,返璞归真之控制台程序_baita96的博客-CSDN博客”、A34课“深入浅出CChart 每日一课——快乐高四第三十四课 不忘初心,Fortran控制台绘制曲线图_baita96的博客-CSDN博客_fortran绘制函数图像”、A35课“深入浅出CChart 每日一课——快乐高四第三十五课 砥砺前行,Fortran控制台绘制等高线云图_baita96的博客-CSDN博客”、A49课“深入浅出CChart 每日一课——快乐高四第四十九课 旧石器时代,老血狂喷之控制台窗口绘图_baita96的博客-CSDN博客”、A50课“深入浅出CChart 每日一课——快乐高四第五十课 新石器时代,轻装上阵之EasyX窗口绘图_baita96的博客-CSDN博客”。 重点请参考A49课。 A56.15 CChart数据量问题问:CChart最大可以支持多少数据点? 答:理论上,CChart支持的数据点由系统的内存决定。一个数据点由两个double数据组成,共占据16Byte。因此,32位版总共大致能用2G内存,可以支持的数据点数大概是几千万个,对于64位版,则基本没有限制。试验也可以发现,32位版如果数据点达到亿量级,程序直接崩溃,而64位版则没有问题。 在实用层面,还要考虑软件的响应速度等问题,因此支持的数据点没有上面那么多。 这里要分三种情况分析。 情况1、静态图像,无消息响应。 静态图像是指图像中不需要动态增删数据点。 在这种情况下,CChart支持的数据点可以达到理论上那么多。基本上,支持千万量级数据点是没有问题的,64位版甚至可以支持10亿、百亿。当然,数据点太多,您在程序开始读入数据的时候要花较长的时间。 情况2、静态图像,有消息响应。 这种情况下,由于消息响应时图像可能需要重绘,大数据量时重绘也比较耗时。 CChart对这种情况下的重绘进行了优化,如果数据量为几百万,同时图像不改变大小,一般情况下重绘时间不会超过1秒,这是可以接受的。 如果图像大小改变,重绘时间会长一些。只要不是经常发生,我们认为改变图像大小的情况可以忽略。 因此,在这种情况下,CChart支持的数据量大概为百万量级。 情况3、动态图像。 动态图像是指图像中不断增删数据点。 这种情况下,一般数据量达到10万,可能就能感觉到一些卡顿了。 因此,此时CChart支持的数据量大概为十万量级。 作为一款免费开源软件,CChart能达到这个水平,笨笨已经做了很大努力。 这里对比一款商业软件ProEssentials的情况。ProEssentials有三种版本:Pro、Standard和Lite。Pro版是最完整的版本,开发无任何限制;Standard版最多支持8000个数据点和800个注释;Lite版支持1000个数据点和100个注释。可以看到,如果不买最贵的Pro版,您花了钱还受到了很多限制。同时笨笨认为,大量数据点主要用于曲线图绘制,单就曲线图绘制来看,CChart的功能并不比ProEssentials弱。当然其它类型的图像的确不是CChart的强项。 为了提高大数据量时的性能,笨笨在CChart的基础上,专门开发了一个拓展库,名为CHugeChart,这个库在千万数据量的情况下,无论是键盘鼠标消息还是增删数据,响应都很丝滑,也有朋友把这个库用到了项目中,反应良好。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 15:28:30- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |