使用Openxal框架开发加速器模型相关的java应用程序

1 复制模板,并重命名

CSNS Openxal Github项目提供了开源的Openxal框架核心代码与一系列应用程序。在apps文件夹下可以找到”acceleratorapplicationtemplate“程序模板。我们在此基础上开发满足我们需求的加速器模型相关的java应用程序。

这里我们以”mysql2accelerator“程序的开发为例。

2 一个程序的资源文件夹构成:acceleratorapplicationtemplate为例

在这里插入图片描述

2.1 resources文件夹

该文件夹下保存了GUI设计相关的文件,一般是由”bricks“程序生成的xml文档”gui.bricks“。acceleratorapplicationtemplate程序开始运行时,将从该文件夹读取”gui.bricks“文件,然后自动地生成对应java程序窗口及窗口内控件。

2.2 src\xal\app\acceleratorapplicationtemplate文件夹

该文件夹下保存了程序核心的java类以及Main函数入口。我们在此模板基础上开发程序时,对Main.java和TemplateDocument.java的修改较少。

3 MVC设计模式

MVC的全名是Model View Controller,是模型(Model)-视图(view)-控制器(controller)的缩写,是一种设计模式。大多现有Openxal程序遵循这一设计模式,在此不加赘述。相关内容:MVC设计模式介绍

在”mysql2accelerator“程序的开发中,编写了以下几个类:

  • Mysql2acceleratorController:定义GUI界面的后端功能和刷新行为。
  • Mysql2acceleratorWindow:使用Java swing进行GUI前端窗口设计。
  • SQL_dialog:继承于JDialog,配置对话框,用户将在对话框中输入MySQL数据库连接相关信息。
  • SQLBaseDAO:SQL数据库的数据接口对象,定义了连接、查询、执行SQL语句等方法。
  • SQLControllerModel:维护与SQL数据库的连接,将取得的数据转化为程序中需要的格式。

其他几个类分别是:

  • Main:程序mysql2accelerator的Main函数入口
  • ChannelMonitor:监控PV值变化,在PV值变化后立即更新对应表格中Live Value的数值。
  • Mysql2acceleratorDocument:将程序状态保存为xml格式的文档,或从xml格式文档中恢复程序配置。

4 程序开发核心:模板中java文件修改与编写

4.1 对Main.java的修改

  1. 程序可读文档拓展名定义:此处的文档指的是保存程序状态的xml格式的文档,此处定义”mysql2accelerator“程序文档的拓展名为m2a,当然也可以是任何自定义的符合规则的拓展名。
public String[] readableDocumentTypes() {
    return new String[] {"m2a"};
}
  1. 程序可写文档拓展名定义:所指文档同上
public String[] writableDocumentTypes() {
   return new String[] {"m2a"};
}
  1. 定义应用名:
public String applicationName() {
    return "Mysql2Accelerator";
}

4.2 对TemplateDocument.java的修改

首先重命名为合适的名称,Mysql2acceleratorDocument.java。

  1. 自定义选中的sequence改变后执行的行为,这里执行updateAcceleratorTableView(),将会更新Accelerator Table显示的数据。
/** 选中的sequence改变后执行的行为 */
public void selectedSequenceChanged() {
	if (selectedSequence != null) {
		System.out.println("Sequence selected: " + selectedSequence.getId());
		APP_CONTROLLER.updateAcceleratorTableView();
		setHasChanges(true);
	}
}

4.4 对TemplateWindow.java的修改

这一文件定义了程序前端界面构成与组件排布。在我们的开发中,删除了原有的内容,使用Java Swing编写了程序的前端界面。Swing 是一个为Java设计的GUI工具包,Swing是JAVA基础类的一部分,包括了图形用户界面(GUI)器件如:文本框,按钮,分隔窗格和表。现有的Openxal程序的前端窗口和控件大多属于Swing。(Swing 介绍

将TemplateWindow.java重命名为Mysql2acceleratorWindow.java。具体代码如下:

package xal.app.mysql2accelerator;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;


/**
* GUI前端设计。继承于JPanel,将添加到Openxal框架中预先配置好的加速器程序窗口"xal.extension.application.smf.DefaultAcceleratorWindow"中去。
* @ClassName Mysql2acceleratorWindow 
* @Description GUI前端设计。继承于JPanel,将添加到Openxal框架中预先配置好的加速器程序窗口"xal.extension.application.smf.DefaultAcceleratorWindow"中去。
* @author Fangnan Li
* @date 2022-04-06 14:50
*  
*/
class Mysql2acceleratorWindow extends JPanel {
    /** serialization ID */
    private static final long serialVersionUID = 1L;  
    
	private JTable Database_Table;
	private JTable Accelerator_Table;
	private JButton Link_to_MySQL_Button;
	private JButton Refresh_Database_Button;
	private JButton Send_Data_Button;
	private JButton Check_All_Button;
	private JButton Uncheck_All_Button;
    
    /** Creates a new instance of MainWindow */
    public Mysql2acceleratorWindow() {
        super();
        this.setBorder(new EmptyBorder(5, 5, 5, 5));
		this.setLayout(new BorderLayout(0, 0));
		JPanel Above_Box = new JPanel();
		Above_Box.setBorder(new EmptyBorder(10, 10, 10, 10));
		this.add(Above_Box, BorderLayout.NORTH);
		Above_Box.setLayout(new BoxLayout(Above_Box, BoxLayout.X_AXIS));
		
		Link_to_MySQL_Button = new JButton("Link to MySQL");
		Above_Box.add(Link_to_MySQL_Button);
		
		Component horizontalGlue_2 = Box.createHorizontalGlue();
		Above_Box.add(horizontalGlue_2);
		
		JPanel Below_Box = new JPanel();
		Below_Box.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), new EtchedBorder(EtchedBorder.LOWERED, null, null)));
		Below_Box.setBounds(new Rectangle(10, 10, 10, 10));
		this.add(Below_Box, BorderLayout.CENTER);
		Below_Box.setLayout(new BoxLayout(Below_Box, BoxLayout.X_AXIS));
		
		JSplitPane Split_Pane = new JSplitPane();
		Split_Pane.setResizeWeight(0.58);
		Below_Box.add(Split_Pane);
		
		Box Database_Box = Box.createHorizontalBox();
		Database_Box.setBorder(new EmptyBorder(3, 3, 3, 3));
		Database_Box.setBounds(new Rectangle(0, 0, 500, 0));
		Split_Pane.setLeftComponent(Database_Box);
		
		Box Database_Data_Box = Box.createVerticalBox();
		Database_Box.add(Database_Data_Box);
		
		JPanel Left_Control_Box = new JPanel();
		Database_Data_Box.add(Left_Control_Box);
		Left_Control_Box.setLayout(new BoxLayout(Left_Control_Box, BoxLayout.X_AXIS));
		
		Refresh_Database_Button = new JButton("Refresh");
		Left_Control_Box.add(Refresh_Database_Button);
		
		Component horizontalGlue_1 = Box.createHorizontalGlue();
		Left_Control_Box.add(horizontalGlue_1);
		
		JScrollPane Left_Table_Box = new JScrollPane();
		Left_Table_Box.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		Database_Data_Box.add(Left_Table_Box);
		
		Database_Table = new JTable();
		
		Left_Table_Box.setViewportView(Database_Table);
			
		Box Send_Data_Box = Box.createHorizontalBox();
		Database_Box.add(Send_Data_Box);
		
		Send_Data_Button = new JButton(">>");
		Send_Data_Box.add(Send_Data_Button);
		
		Box Accelerator_Box = Box.createVerticalBox();
		Accelerator_Box.setBorder(new EmptyBorder(3, 3, 3, 3));
		Accelerator_Box.setBounds(new Rectangle(0, 0, 500, 0));
		Split_Pane.setRightComponent(Accelerator_Box);
		
		JPanel Right_Control_Box = new JPanel();
		Accelerator_Box.add(Right_Control_Box);
		
		Check_All_Button = new JButton("Check All");
		Check_All_Button.setHorizontalAlignment(SwingConstants.RIGHT);
		
		Uncheck_All_Button = new JButton("Uncheck All");
		Uncheck_All_Button.setHorizontalAlignment(SwingConstants.RIGHT);
		Right_Control_Box.setLayout(new BoxLayout(Right_Control_Box, BoxLayout.X_AXIS));
		
		Component horizontalGlue = Box.createHorizontalGlue();
		Right_Control_Box.add(horizontalGlue);
		Right_Control_Box.add(Check_All_Button);
		Right_Control_Box.add(Uncheck_All_Button);
		
		JScrollPane Right_Table_Box = new JScrollPane();
		Right_Table_Box.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		Accelerator_Box.add(Right_Table_Box);
		
		Accelerator_Table = new JTable();
		Right_Table_Box.setViewportView(Accelerator_Table);
    }
    
    public JTable get_Database_Table() {
		return Database_Table;
	}
    
    public JTable get_Accelerator_Table() {
		return Accelerator_Table;
	}
    
    public JButton get_Link_to_MySQL_Button() {
		return Link_to_MySQL_Button;
	}
    
    public JButton get_Refresh_Database_Button() {
		return Refresh_Database_Button;
	}
    
    public JButton get_Send_Data_Button() {
		return Send_Data_Button;
	}
    
    public JButton get_Check_All_Button() {
		return Check_All_Button;
	}

    public JButton get_Uncheck_All_Button() {
		return Uncheck_All_Button;
	}
}

以上代码生成的窗口效果如下图所示:
在这里插入图片描述

4.4.1 Java Swing的GUI开发工具:WindowBuilder

WindowBuilder是eclipse中的插件,通过拖动控件设计GUI界面,所见即所得。上述Java代码便是使用WindowBuilder设计后自动生成的。
WindowBuilder安装教程,在线安装或离线包下载安装都可:windowBuilder最新的安装教程

5 程序开发核心:自定义类和功能

5.1 Mysql数据库相关

5.1.1 SQL数据库的数据接口对象:SQLBaseDAO.java

修饰符和类型方法说明
voidcloseConnection()关闭与Mysql数据库的连接
ResultSetexecuteQuery(String sql, String[] paras)执行SQL数据查询
intexecuteUpdate(String sql, String[] paras)执行SQL语句,增删查改
voidgetConnection()连接数据库
booleanisConnectionAvailable()返回数据库连接是否可用

5.1.2 对话框,输入MySQL数据库连接相关信息:SQL_dialog.java

继承于JDialog。定义了对话框的内容,如下所示:
在这里插入图片描述
用于获取用户输入,然后根据相关信息建立与MySQL数据库的连接。
如果连接失败,将弹出如下的对话框提示。失败可能有许多原因:输入信息错误、MySQL数据库服务端错误、网络连接错误等等。
在这里插入图片描述
若成功连接,在左侧的列表中将显示读回的数据。这一数据显示功能由SQLControllerModel.java和Mysql2acceleratorController.java完成。
在这里插入图片描述

5.1.3 维护与SQL数据库的连接,将取得的数据转化为程序中需要的格式:SQLControllerModel.java

负责实例化SQL_dialog对象,从对话框中获取用户输入的信息,然后利用这些信息建立与SQL数据库的连接。这一类中的主要方法有:

修饰符和类型方法说明
voidcloseSQLConnection()关闭连接
VectorgetColumnNames()返回查询到数据表的列名
voidgetSQLConnection()与SQL数据库连接
VectorgetTableData()返回查询到数据表的表中数据
booleanisConnectionPrepared()检查是否数据库的连接可用
private voidupdateValues()从对话框中获取的IP、PORT、USER、PASS、DBNAME、TABLENAME等数据

5.2 Mysql2acceleratorController.java

是程序功能实现最核心的部分。设置GUI界面的后端功能,定义各个按钮控件的点击事件、Table等数据展示控件的数据更新行为。
主要方法包括:

修饰符和类型方法说明
private voidconfigure_Link_to_MySQL_Button(xal.extension.bricks.WindowReference windowReference)定义Link to MySQL按钮事件,即打开对话框,等待用户输入MySQL相关连接配置
private voidconfigureCheckAllButton(xal.extension.bricks.WindowReference windowReference)定义Check All按钮事件,即选中加速器表格中的所有node
voidconfigureMainWindow(xal.extension.bricks.WindowReference windowReference)为程序主界面MainWindow添加控件
private voidConfigureSendDataButton(xal.extension.bricks.WindowReference windowReference)初始化窗口时调用,定义窗口中间的">>" Send Data按钮事件
private voidconfigureUncheckAllButton(xal.extension.bricks.WindowReference windowReference)定义Uncheck All按钮事件,即取消选中加速器表格中的所有node
private voidmakeAcceleratorTableView(xal.extension.bricks.WindowReference windowReference)初始化窗口时调用,配置展示加速器相关数据的表格
private voidmakeDatabaseView(xal.extension.bricks.WindowReference windowReference)初始化窗口时调用,配置展示数据库数据的表格,定义Refresh按钮事件
voidupdateAcceleratorTableView()更新加速器表格中的数据,一般在切换sequence后调用
voidupdateDatabaseView()更新数据库表格中的数据,表格列宽自适应相关配置

5.3 读取和设置磁铁电流的方法

xal.smf.impl.Electromagnet是 xal.smf.AcceleratorNode的子类。在加载xal配置文件的时候,所有Node类都被实例化。我们调用Electromagnet的getMainSupply()方法,获取磁铁对应电源对象MagnetMainSupply。

  • 调用MagnetMainSupply的getCurrent()方法读取电流值。
  • 调用MagnetMainSupply的setCurrent(double val)方法设置电流值。

此外,值得一提的是,MagnetMainSupply类还提供了getField()、setField(double newField)、getChannel( final String handle )等方法。

6 程序功能介绍

本程序的主要功能是将MySQL数据库中保存的参数数据,设置到加速器EPICS控制系统的相应PV中去。设置的参数可选可调整,被设置的设备可选择,实时值也在程序中实时更新显示。目前设置的所有设备均为电磁铁,设置PV量为磁铁电流。

6.1 根据用户输入连接并获取MySQL中的数据表

在这里插入图片描述
在这里插入图片描述

6.2 数据库连接失败提示

在这里插入图片描述

6.3 自适应的列宽,避免列宽过小

  • 列数少时,充满Panel
    在这里插入图片描述

  • 列数多时,出现横向滚动条
    在这里插入图片描述

6.4 数据库列表支持数据修改,便于参数设置的微调,但不影响数据库中数据

在这里插入图片描述

6.5 加速器参数列表

根据加载的xal加速器配置文件和选中的sequence,显示加速器信息列表。列表包含加速器Node名称、类型、位置、PV值类型、实时值、设置的PV名等信息。
在这里插入图片描述

6.8 Check All与Unheck All按钮:全选或取消全选需要设置的Node

在这里插入图片描述

6.7 选中MySQL数据表中的一条数据,发布给CheckBox选中的Node,即设置相应PV

MySQL数据表的列名即为Node ID,对应于加速器列表中的Node ID。点击窗口中部的“>>”按钮,设置EPICS控制系统对应PV值(Node名、PV名等参数在xal配置文件中设置)。

若加速器表中的Node不在数据库表中,则console窗口出现信息提示:
在这里插入图片描述
若设置的数据包含空值或错误格式,console窗口则会提示:
在这里插入图片描述

7 注释及javadoc文档的生成

根据特定格式的注释,能够自动化地生成程序的javadoc文档。在eclipse中,通过菜单栏的File->Export->Java->javadoc生成javadoc文档。
在这里插入图片描述

文档为一系列html格式的文件,如下图所示。
在这里插入图片描述
生成的文档为html格式,可在浏览器中打开,内容包含项目结构、程序包、类、方法、变量的总结和描述。
在这里插入图片描述
在这里插入图片描述

7.1 注释格式

为了生成javadoc文档,需按照特定格式编写注释。主要对类、方法、变量的功能描述进行注释。一下只是一种举例,可以按照自己的需求规定注释格式,一般只需保证一个项目使用相同的注释格式、注释模板。(Javadoc详解

  1. 类的注释
    在这里插入图片描述

  2. 方法注释,方法可能由传入参数,也可能没有传入参数,以下是这两种情况注释的举例。
    传入参数为url
    无传入参数的方法

  3. 变量注释
    在这里插入图片描述

Last

Feel free to contact us by email: fnli@stu.pku.edu.cn

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值