没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
转帖|其它|编辑:郝浩|2010-08-13 12:15:49.000|阅读 841 次
概述:本文适用于 GUI 开发人员,这些开发人员要编写可移植、可重用和速度更快的控件,用于看到量大且复杂的数据。当前存在一些常见的问题,如性能差,还存在一些可用性问题,如不能清楚地显示大型数据集,所以用户可以很容易地通过浏览本文进行分析。另外,程序数据结构和可视数据表示彼此之间的依赖性通常也变得非常强。因此,控件的专用性变得非常强,如果不进行重要修改,就不能在其他应用程序中使用。本文提供了一种方法,可用来设计复杂的控件,解决以上讨论的问题。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
本文适用于 GUI 开发人员,这些开发人员要编写可移植、可重用和速度更快的控件,用于看到量大且复杂的数据。当前存在一些常见的问题,如性能差,还存在一些可用性问题,如不能清楚地显示大型数据集,所以用户可以很容易地通过浏览本文进行分析。另外,程序数据结构和可视数据表示彼此之间的依赖性通常也变得非常强。因此,控件的专用性变得非常强,如果不进行重要修改,就不能在其他应用程序中使用。本文提供了一种方法,可用来设计复杂的控件,解决以上讨论的问题。本文中,将使用图表查看器控件的一些示例来说明基本概念。这些概念还可以适用于多种多样的其他控件。
定义
图表代表一组对象及对象之间的关系。对象叫做节点。节点之间的关系叫做边。因此,一个可视图表就是一组节点(有或没有标签的正方形、长方形、圆等)和连接节点的边(直线或曲线)。定义节点与边的位置的算法叫做布局。
请注意,节点中可以包含其他节点和边(子图表)。如果某些节点的边从这些节点起连接到任一个给定节点,那么这些节点叫做这个给定节点的父节点。如果某些节点的边从任一个给定节点起连接到这些节点,那么这些节点叫做这个给定节点的子节点。
图表控件中的常见问题
在很多应用程序中都使用图表控件来显示数据。如果要在不同的应用程序中使用相同的图表控件,就必须提供一种方法来自定义该图表控件。这种自定义一定不能影响应用程序的性能。以下是在不同应用程序中应用控件时可能遇到的各种问题列表:
图表控件上必须提供滚动和缩放工具才能浏览大型图表。下一部分说明如何灵活地解决这个问题而不降低任何性能。
自定义的外观和用户交互
通常您可以区别控件的两个部分,即区别数据元素与核心部分,数据元素表示数据的各个部分,核心部分负责将数据组织为一个整体。图表数据元素由节点和边组成。当需要时,核心部分会使用数据元素的自定义版本来提供一些功能,如滚动、缩放、绘图和事件处理。例如,当您单击鼠标按钮时,核心部分会定义这个事件发生的位置。如果事件发生在某个数据元素上,那么事件信息会传递到这个数据元素的处理程序,此外核心部分会处理事件本身。
图表中有两样东西项目会随着不同应用程序而改变,您应当进行自定义。一个是数据元素的外观与行为;另一个是组织元素的方式。如果要很容易地自定义控件,就需要为这些东西定义界面,然后仅通过界面将这些东西用于控件。所以,如果要进行某种更改,只需要采用新的方式实现界面,无需更改控件中的代码。这就是所谓的“策略”模式。
图表控件采用了以下策略:
class INodeHandler
{
public:
// 绘制给定的节点
virtual void Draw(Node) = 0;
// 返回描述正方形的尺寸。此函数在布局中用来确定
// 节点位置,没有交叉点。
virtual idvc::dsize GetSize(Node)= 0;
// 设置所有后续 Draw 调用函数中要使用的缩放系数。此函数
// 在实现缩放时由控件的核心部分使用。
virtual void SetZoomFactor(double f) {};
// 处理鼠标单击事件
virtual ChangesType HandleClick(Node n, double inX, double inY,
int kstate, idvc::MouseButton Button);
// 处理工具提示事件
virtual ChangesType HandleOnTooltip(Node n, CGraphTooltipEvent* pEvent); }; // 结束 INodeHandler
}; // 结束 INodeHandler
class ILayout
{
public:
/// 这个函数应为给定节点内的所有节点
/// 生成新布局,并计算新布局的尺寸。内部节点的位置
/// 必须根据给定节点的左上角进行定义,
/// 假使给定节点的坐标是 (0,0)。
virtual void Make( Node ) = 0;
/// 与 Make 一样,但是应使用以前布局
/// 的信息,然后尝试保持已摆放节点
/// 的相对位置。
virtual void Update( Node ) = 0;
/// 这个函数在更改了已拥有节点的尺寸
/// 或跳过 ILayout 的参数时
/// 用于重新计算节点与边的坐标。
/// 它假定以前调用过 Make 或 Update,而且
/// 所有已拥有节点的尺寸。与 Make 和 Update 不同,它
/// 不可递归。
virtual void Resize( Node ) = 0;
};
以上类定义了三种不同情况下的布局策略函数,即:
定义这种区别的主要目的是为了减少布局计算时间。如果向某个大型图表中添加一个节点,就不需要重新计算整个图表的布局。
快速绘制和事件处理
应解决的最后但并非不重要的问题是,如何快速对事件做出反应(至少是重新绘制事件)。当处理大型数据集时,控件应允许您快速地滚动和缩放内容。此处的主要问题是,事件处理和绘图函数是由用户定义的(通过上面描述的界面),而控件中的每个元素在绘图和事件处理中可以采用自己的实现方式。因此,不能保证快速进行处理。不过,可以减少元素函数调用的数量。
void CContent::DrawContent(idvc::IPainter* p)
{
// 确定应重新绘制的无效长方形
idvcfrw::CInvalidRegion InvalidRegions(draw_rect, valid_rect);
for(int i = 0; i < InvalidRegions.size(); ++i)
{
// 得到对应于下一个无效区域的长方形
idvc::drect rect = InvalidRegions[i];
// 查找并重新绘制与无效长方形相交的节点
NodeSet nodes = graph->HitNodeTest(rect.left, rect.top, rect.right, rect.bottom);
for_each(nodes.begin(), nodes.end(), DrawNode(p,scale));
// 查找并重新绘制与无效长方形相交的边
EdgeSet es = graph->HitEdgeTest(rect.left, rect.top, rect.right, rect.bottom);
for_each(es->Begin(), es->End(), DrawEdge(p,scale));
};
};
利用窗口事件中也拥有发生事件的点或长方形这一事实,可采用与绘图类似的方式来组织事件处理(至少对于窗口事件而言)。这样,控件可以确定节点与边,这些节点与边受任何给定事件的影响,而且只针对这些元素调用事件处理函数,因此大大地减少了处理时间。
数据加载
当处理大型数据集时,这些数据集通常存储在某个外部数据源中。外部数据源可能随着应用程序的不同而有所不同(文件、数据库等)。因此,您需要使用一种机制来独立地从外部数据源快速地加载数据。快速常常意味着加载部分数据,因为如果要真正地获得大型数据集,无论如何都不能快速地执行加载。但是,控件一般只需要数据中的一小部分来进行处理,您应当只加载这一部分数据。
有两种方法可用来实现部分加载。第一种类似于上面说明的快速绘图和事件处理。您需要定义一个界面,这个界面与数据源无关,可用来加载数据。您应当尝试实现以下方法,即可以用于定义需要加载的数据,而不是执行全部加载。然后可以定义应加载的数据元素,通过界面只针对这些元素调用加载函数。
不总是可以将元素定义为自动加载。另一种实现部分加载的方法是让用户输入。这种情况下,用户负责定义应何时加载数据,以及应加载哪些数据。
ChangesType PortNodeHandler::HandleClick(Node n, double inX, double inY,
int kstate, idvc::MouseButton Button)
{
ChangesType processed = ctNone;
idvc::dpoint pos = n->GetPosition();
idvc::dsize size = n->GetSize();
// 如果节点没有嵌套的节点且使用鼠标左键对其单击
if ( (n->GetOwned()->GetCount() == 0) && (Button == idvc::mbLeft) )
{
if (node_drawer.IsLeftPortClicked(n, inX, inY))
{
bool hide = ( CountAllParents(n) == CountVisibleParents(n) );
// 如果所有父节点可见
if( hide ) Fold(n, fdParents);
else Unfold(n, fdParents);
}
else if (node_drawer.IsRightPortClicked(n, inX, inY))
{
bool hide = ( CountAllChildren(n) == CountVisibleChildren(n) );
// 如果所有子节点可见
if( hide ) Fold(n, fdChildren);
else Unfold(n, fdChildren);
}
else
{
// 如果用户单击节点本身,则会选中它
SetFlag(n, Node::fSelected, !IsFlagSet(n, Node::fSelected));
};
processed = ctAll;
};
OnClick.fire(n, inX, inY, kstate, Button);
return processed;
};
结论
以下是创建可移植、快速控件中的主要概念:
下图描述了如何将这些原则应用到图表控件:
图 1. 图表设计
使用这些原则可获得高度自定义、可移植且快速的控件,这些控件可处理大型数据集,也可进行调整以便用于很多应用程序。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:网络转载面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号