• 开源纯C#工控网关+组态软件(六)图元组件


    一、   图元概述

    图元是构成人机界面的基本单元。如一个个的电机、设备、数据显示、仪表盘,都是图元。构建人机界面的过程就是铺排、挪移、定位图元的过程。

    图元设计是绘图和编码的结合。因为图元不仅有显示和动画,还有背后操纵动画的控制逻辑。

    一个好的图元设计框架,应该最大限度提高设计的效率和专业程度。

    因为你找到一个会做美工的码农,和会写代码的美工,都很困难,但是单独找码农和绘图员却一抓一大把。所以专业性意味着用人的灵活性,和省钱。而你招来一个美工,一个码农,合作完成一个图元组件,必须考虑减少两人的交互,最好埋头各干各的。并行作业,才有最高效率。

    可以通过以下手段提高界面开发效率:

    • 前后端分离

    前后端分离的设计模式有很多优点。前后端对设计者的要求是不同的。。

    前端设计者需要考虑的是界面更直观、美观、清晰、大气,可以熟练使用绘图工具(例如Blend),可以不会编程。

    后端设计者要考虑的是业务逻辑,如何有条不紊、准确执行。可以不会画图,但一般必然熟练编码,使用设计工具(如Visual Studio)。

    前后端分离便于设计者术业有专攻,前后端分工协作,互不干扰,并行工作,提高效率。

    • 专业的前端设计工具

    对于绘图员或美工,一个简单易用、同时又有强大功能的趁手设计器是必须的。

    绘图板、动画、整合、调色板,美工的全套装备必须齐全;网格定位、缩放、旋转、保存、撤销,常规的设计器功能必须应有尽有。

    • 尽可能少的编码

    很多行业都有庞大的图元库。各种设备、开关、构件,各种非标组件,不断会有新的图元入库。

    因此,力求用最少的代码实现尽可能多的功能,最大限度提升开发效率。一个强大的基类和一个方便的继承是必要的。

    二、   前后端分离的设计模式

    • 通过WPF实现前后端分离

    看看百度百科对WPF的介绍:WPF(Windows Presentation Foundation)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分。

    它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。

    WPF通过一种MVVM(Model-View-ViewMode)的设计模式实现界面与编码解耦。界面元素的颜色、动画、形状,可以方便的与代码类的属性绑定(Binding)。

    绑定的便利在于,后台类的某属性变化,马上会自动反映到界面的变化,无需编写代码;界面元素的变化,也马上会触发属性值的改变,这种方式天然适合人机界面的前后端分离设计。

    同时,WPF提供XAML文件,是一种声明式编程方式,类似于Android的界面文件、HTML,界面设计者与代码编写者只需要通过XAML文件交互,进一步达成前后端分离并行作业的目的。

    •  前后端交互的内容

    绘图员的工作:

    使用Blend绘图,使用故事板(Storyboard)制作动画,定义动画的视图状态(VisualState),绑定属性如:

    Text="{Binding BinName, RelativeSource={RelativeSource TemplatedParent}}"

    码农的工作:

    定义一个CustomControl。继承HMIControlBase

    定义依赖项属性如Running:

                public static readonly DependencyProperty RunningProperty = DependencyProperty.Register("Running", typeof(bool), typeof(Elevator),
                new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender,
                new PropertyChangedCallback(OnValueChanged)));

    属性变化事件切换视图状态如

    VisualStateManager.GoToState(this, _funcRun () ? "Run" : "Stop", true);

    就这么简单。

    三、   绘图与动画

    • 强大的设计工具:Blend

    Blend是VS2010起微软提供的专业设计工具。早期曾经有三贱客(Blend,Design, Encoder ),后两者已经合并入Blend。

    在 Expression Blend 中,可以在美工板上绘制形状、路径和控件,然后修改其外观和行为,从而直观地设计界面元素。可以导入图像、视频和声音,还可以导入和更改三维对象。

    可以创建Storyboard实现帧动画,定义状态(VisualState),并设计触发器(Trigger)触发动画。还可以定义样式(Style)。

    Blend对美工人员是简单易上手的。按我的经验,对于习惯AutoCAD工具的绘图工程师,熟练掌握Blend一般在两周内,就可以绘制复杂的动画图形。

    所有的图元组件均为CustomControl类型,这样编辑好的图元文件会自动加入到Generic.xaml文件。相应的图元模板可在Blend内重新编辑。

     

    • 用代码实现动画

    如果不用Blend,也可以用代码直接实现动画。部分对性能要求高、使用频繁的图元组件如Guage,LinkLine,可以继承Control的OnRender方法并使用StreamGeometry这类的底层API绘图,以达到最佳的性能。

    StreamGeometry的优点是调用底层绘图API,不生成多余的对象,而Blend在生成图形过程中有大量冗余元素和对象,复杂的层次结构,在对性能要求较高的场合略显笨重。

    四、   强大的图元基类

    为了尽可能减少编码,需要在图元基类(HMIControlBase) 中实现尽可能多的功能;但又不能包办一切,牺牲图元自身的“个性”。要实现简洁、强大、可扩展。

    因此,我在图元基类实现了所有界面元素共有的几个基本功能:

    • 连线。

    为了实现方便的连线,需要能自行设置图元的锚点,作为拖放连线的连接点。

     

    继承GetLinkPositions方法,锚点分上下左右四个,每个锚点用一个Point确定相对位置。如果只有一个锚点,就返回单一的LinkPosition如下:

      public override LinkPosition[] GetLinkPositions()
            {
                return new LinkPosition[1]
                    { 
                        new  LinkPosition(new Point(0.75,0),ConnectOrientation.Top),
                    };
            }
    • 绑定变量表达式。

    只要继承基类,就可以弹出变量组态界面。

     

    可以自行定义左边的属性树。即继承GetActions方法。注意这个树状结构支持嵌套,如某设备带两个电机(Motor),则电机的属性列表会作为树的子节点显示。

    public override string[] GetActions()
            {
                return new string[] { TagActions.VISIBLE, TagActions.CAPTION, TagActions.RUN, TagActions.ALARM, TagActions.DEVICENAME };
            }
    • 动画显示。

    继承SetTagReader方法,只要相关Tag变化,就会触发动画脚本。如

    public override Action SetTagReader(string key, Delegate tagChanged)
            {
                switch (key)
                {
                    case TagActions.RUN:
                        var _funcInRun = tagChanged as Func<bool>;
                        if (_funcInRun != null)
                        {
                            return delegate { VisualStateManager.GoToState(this, _funcInRun() ? "Running" : "NotRunning", true); };
                        }
                        else return null;
                }
                return base.SetTagReader(key, tagChanged);
            }

    VisualStateManager.GoToState方法根据不同的状态字,触发了在Blend里定义的故事板动画。

    五、   如何实现:增加新图元

    图元设计流程:

     

    六、   下面的计划

    写一系列帖子,把架构、原理讲清楚。大致如下:

    • 网关层接口概述
    • 上下位机通讯原理
    • 如何实现一个设备驱动
    • 如何设计图元
    • VS插件模块及原理
    • 归档模块及文件格式
    • 如何进行功能扩展
    • 组态变量表达式实现

    github地址:https://github.com/GavinYellow/SharpSCADA。QQ群:102486275

  • 相关阅读:
    redhat yum替换成CentOS yum 并修改源
    C++11新特性实验
    常见的安装包制作程序installer
    如何在数据库中删除并添加唯一索引?
    springboot中的restTemplate工具类
    如何使用swagger(一)
    The POM for com.qingmu:entity:jar:1.0.0-SNAPSHOT is missing, no dependency information available
    java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes
    在使用postman中配置返回html页面
    Springboot中设置返回数据的时间格式
  • 原文地址:https://www.cnblogs.com/evilcat/p/7909578.html
Copyright © 2020-2023  润新知