JAVA Applet 实现工作流设计器

很久没有更新博客了,不是偷懒,而是去年一年的时间都在编写一个快速JAVA开发框架ARK,终于有所小成,才有了闲情逸致没事写点小玩意儿,JAVA Swing自己很少关注,Applet也是如此,从学习Swing和Applet到写出这东西只花了2天时间,算是一些自己的学习心得和成果,希望各位看客多多交流,虽然Applet和Swing不是我工作的重点,偶尔当消遣了。



 

 

 

言归正传,这是一个工作流系统中的流程设计器,整个设计完全面向接口,所以有比较好的扩展性,小弟我水平有限,一些功能就没有加上,有兴趣的XD可以完善这些代码(其实大部分功能都已经实现了,包括流程图路径验证,只是现在只能绘制流程生成XML,没有反向去实现将XML生成流程图),可能自己想起来会再把他翻出来改改,在某个时间将图形转换成HTML能够直接在网页上显示,为什么这么干,你懂得!!

 

package com.applet.flows;

import java.awt.Container;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.MouseInputAdapter;

import com.applet.flows.attr.NodeAttribute;
import com.applet.flows.panel.FlowLine;
import com.applet.flows.panel.FlowPanel;

public abstract class NodeButtonSupport extends JButton implements INodeButton {

	private Collection<INodeButton> childs = null;
	
	private Collection<INodeButton> parents = null;
	
	private int id = -1;
	
	protected DropTarget dropTarget = null;
	
	public NodeButtonSupport(){
		this.childs = new Vector<INodeButton>();
		this.parents = new Vector<INodeButton>();
		this.dropTarget = new DropTarget(this,DnDConstants.ACTION_COPY,this,true);
		new MouseApdaterListener(this);
		this.setSize(100, 40);
		this.setLocation(0, 45);
	}
	
	public ImageIcon getIcon(){
		return null;
	}
	
	public final String[] asXML() {
		String xml = "";
		xml = "<Node id=\"" + this.getID() + "\" type=\"" + this.getType() + "\" name=\"" + this.getText() + "\" x=\"" + this.getX() + "\" y=\"" + this.getY() + "\" />";
		String to = "";
		for(INodeButton nb:this.getChilds()){
			to += nb.getID() + ",";
		}
		String line = "";
		if(!to.trim().equals("")){
			line  = "<Line from=\"" + this.getID() + "\" to=\"" + to.substring(0,to.length() - 1) + "\" />";
		}
		return new String[]{xml,line};
	}

	public final void init(int id) {
		this.id = id;
		ImageIcon icon = this.getIcon();
		if(icon != null){
			this.setIcon(icon);
		}
		this.init();
	}
	
	public INodeButton getThis(){
		return this;
	}
	
	/**
	 * 判断当某个对象接入子对象后,是否会成为一个循环流程
	 * @param button 接入后的对象
	 * @return true:是一个循环,false:不是循环
	 */
	public boolean isPathed(INodeButton button){
		for(INodeButton nb : this.getChilds()){
			if(nb == button){
				return true;
			}
			if(nb instanceof NodeButtonSupport){
				return ((NodeButtonSupport)nb).isPathed(button);
			}
		}
		return false;
	}
	
	/**
	 * 找到Frame对象
	 * @param jc
	 * @return
	 */
	public FlowPanel getFrame(Container jc){
		if(jc == null){
			return null;
		}
		if(jc instanceof FlowPanel){
			return (FlowPanel)jc;
		}
		return this.getFrame(jc.getParent());
	}
	
	protected abstract void init();
	
	public int getID(){
		return this.id;
	}
	
	public abstract boolean link(INodeButton button);

	public void addParent(INodeButton nb){
		this.parents.add(nb);
	}
	
	public void addChild(INodeButton nb){
		this.childs.add(nb);
	}

	public void dragEnter(DropTargetDragEvent arg0) {

	}

	public void dragExit(DropTargetEvent arg0) {

	}

	public void dragOver(DropTargetDragEvent arg0) {

	}

	public final void drop(DropTargetDropEvent e) {
		DataFlavor ob = e.getCurrentDataFlavors()[0];
		try {
			if(!e.getTransferable().isDataFlavorSupported(ob)){
				JOptionPane.showMessageDialog(null, "应用程序不支持对象序列化\n[" + ob.toString() + "]","错误",JOptionPane.ERROR_MESSAGE);
				return;
			}
			INodeButton db = (INodeButton)e.getTransferable().getTransferData(ob);
			if(db == null){
				JOptionPane.showMessageDialog(null, "应用程序无法读取对象序列化\n[" + ob.toString() + "]","错误",JOptionPane.ERROR_MESSAGE);
				return;
			}
			if(isPathed(db)){
				return;
			}
			if(db.report(this) && this.link(db)){
				this.addParent(db);
				db.addChild(this);
				FlowPanel frame = this.getFrame(this.getParent());
				if(frame == null){
					JOptionPane.showMessageDialog(null, "程序无法找到父容器","错误",JOptionPane.ERROR_MESSAGE);
				}else{
					FlowLine line = new FlowLine(new JButton[]{(JButton)db,this});
					line.setSize(frame.getSize());
					line.setLocation(0,0);
					frame.add(line);
					frame.setText("[" + this.getText() + "]连线成功");
					frame.repaint();
				}
			}
		} catch (Exception e1) {
			this.getFrame(this.getParent()).setText(e1.getClass().getName());
			JOptionPane.showMessageDialog(null, e1.toString(),"错误",JOptionPane.ERROR_MESSAGE);
			e1.printStackTrace();
		}
	}
	@Override
	public void setToolTipText(String str) {
		str =  "[ID=" + this.getID() + "]\n" + str; 
		super.setToolTipText(str);
	}
	
	public void dropActionChanged(DropTargetDragEvent arg0) {

	}
	
	public final Collection<INodeButton> getChilds(){
		return this.childs;
	}
	
	public final Collection<INodeButton> getParents(){
		return this.parents;
	}

	/**
	 * 获取节点类型
	 * @return 节点类型
	 */
	public abstract String getType();
	
	public final class MouseApdaterListener extends MouseInputAdapter{
		
		private NodeButtonSupport support = null;
		
		private Point point = new Point(0, 0);   
		
		public MouseApdaterListener(NodeButtonSupport support){
			this.support = support;
			this.support.addMouseListener(this);
			this.support.addMouseMotionListener(this);
		}
		
		@Override
		public void mouseClicked(MouseEvent e) {
			new NodeAttribute(this.support).setVisible(true);
		}
		
		public void mousePressed(MouseEvent e) {
			if(e.getButton() != 1){
				JComponent com=(JComponent)e.getSource();
				TransferHandler handler = new TransferHandler("this");
				com.setTransferHandler(handler);
				handler.exportAsDrag(com, e, DnDConstants.ACTION_COPY);
			}else{
				this.point = SwingUtilities.convertPoint(this.support, e.getPoint(), this.support.getParent());
			}
		}
		
		@Override
		public void mouseDragged(MouseEvent e) {
			if(e.getButton() != 1){
				Point newPoint = SwingUtilities.convertPoint(this.support, e.getPoint(), this.support.getParent());
				Point btnPoint = new Point((this.support.getX() + (newPoint.x - this.point.x )),(this.support.getY() + (newPoint.y - this.point.y)));
				this.support.setLocation(btnPoint);
				point = newPoint;
				FlowPanel frame = this.support.getFrame(this.support.getParent());
				frame.repaint();
			}
		}
	}
}

 

强调一下,NodeButtonSupport是所有节点的抽象类,如果希望扩展节点类型的XD在增加类型的时候一定别忘了继承他,里面很多算法我都已经实现好了,当然还有两个接口。

package com.applet.flows;

/**
 * 基本XML流程对象
 * 
 * @author 熊浩华 - xionghh
 *
 * 2011-3-10:下午12:29:47-
 */
public interface IFlow {

	/**
	 * 返回该对象的XML分为{节点,连接线}
	 * @return
	 */
	public String[] asXML();
	
	/**
	 * 判断节点是否是合法
	 * @return 当节点存在异常时抛出节点异常信息,否则返回true
	 */
	public boolean checkNode() throws Exception;
	
}

  

 

 

 导出XML文档的接口,所有的节点都实现该接口用于保存时生成XML文档方便,代码派生起来也容易。

 

package com.applet.flows;

import java.awt.dnd.DropTargetListener;
import java.util.Collection;

/**
 * 流程节点接口,用于处理流程的节点
 * 
 * @author 熊浩华 - xionghh
 *
 * 2011-3-10:上午10:02:53-
 */
public interface INodeButton extends DropTargetListener,IFlow {

	/**
	 * 初始化节点对象
	 * @param id 对象ID
	 */
	public void init(int id);
	
	/**
	 * 某个节点拖入,是否允许他和你进行链接
	 * @param button 发起链接的对象
	 * @return 判断是否允许链接,返回true表示允许,false表示不允许操作
	 */
	public boolean link(INodeButton button);
	
	/**
	 * 通知节点,你被拖动到某个节点上,需要你和他进行链接
	 * @param button 需要链接的对象
	 * @return 允许链接返回true,不允许链接返回false
	 */
	public boolean report(INodeButton button);
	
	/**
	 * 获取对象ID
	 * @return 对象ID
	 */
	public int getID();
	
	/**
	 * 添加一个父对象
	 * @param nb
	 */
	public void addParent(INodeButton nb);
	
	/**
	 * 添加一个子对象
	 * @param nb
	 */
	public void addChild(INodeButton nb);
	
	/**
	 * 获取所有子对象
	 * @return
	 */
	public Collection<INodeButton> getChilds();
	
	/**
	 * 获取所有父对象
	 * @return
	 */
	public Collection<INodeButton> getParents();
	
}

 

INodeButton是所有节点的抽象接口,其实很多方法都是想到的时候补上的,开始打算写这个东西的时候没有想把他做成什么样,就当玩票,没仔细去对接口进行详细的设计,很粗略的就描绘了一下。所以看起来有点似是而非。

 

 

最后说一下Demo,压缩包里有tomcat的工程目录,XFLow直接Copy到tomcat下的webapps里就能运行,里面两个包flows.jar和dom4j-1.6.1.jar是签名过的,否则无法当成Applet运行,源码在src里,修改代码后想要在Applet测试通过记得打成包然后对包进行签名。

 

PS:呵呵,老规矩,CSDN(最近穷疯了,分不够了,希望各位给小弟我捧个场)

 

 

 

 

 下载地址 : http://download.csdn.net/source/3082444

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前 言 1 1 概 述 2 1.1 选题背景 2 1.2 组织结构 2 2 所用相关技术和方法 3 2.1 工作流 3 2.1.1 什么叫工作流 3 2.1.2 工作流发展 3 2.1.3 工作流的优点 3 2.2 MVC工作模式 4 2.2.1 MVC设计思想 4 2.2.2 MVC的具体实现 5 2.2.3 MVC的不足 6 2.3 JSP技术介绍 6 2.3.1 JSP的运行原理 7 2.3.2 JSP的生命周期 8 2.3.3 Servlet和JavaBean技术介绍 8 2.3.4 Java 虚拟机 9 2.3.5 JSP访问SQL Server 2000数据库 9 2.4 数据库后台环境配置 10 2.5 系统开发工具简介 10 2.5.1 Dr eamweaver 10 2.5.2 MyEclipse 10 2.5.3 Tomcat 11 2.5.4 SQL Server2000 11 2.5.5 chs_sql2ksp3 12 3 系统需求分析 13 3.1 系统功能分析 13 3.2 系统性能分析 13 3.3 系统方案的确定和评价 13 4 系统总体设计 15 4.1 系统层次模块图 15 4.1.1 营业厅模块 15 4.1.2 收费管理模块 16 4.2 系统数据流程图 16 4.3 数据表设计 18 5 详细设计及编码 21 5.1 编写JAVABEAN 21 5.2 营业厅实现函数 21 5.3 收费厅主要的实现函数 22 5.4 JAVABEAN主要实现模块 22 5.4.1 文字符格式的转换模块(Stringto.java) 22 5.4.2 自动生成验证码(Ran.java) 22 5.4.3 数据库的连接(ConnectionFactory.java) 23 5.4.4 数据库连接的关闭(DatabaseUtils.java)--只提供接口 23 5.4.5 密码修改模块(Common_fuction.java) 24 5.4.6 时间格式转换(timeBean.java) 24 5.4.7 数据统计(counthander.java) 25 5.4.8 营业厅的接口(luruaction.java) 27 5.4.9 营业厅的主要函数实现(luruhander.java) 28 5.4.10 收费厅的主要函数接口 32 5.5 管理员登陆模块 33 5.5.1 管理员登录 33 5.6 营业厅管理模块 36 5.6.1 Left.jsp页面 36 5.6.2 Work.jsp 40 5.6.3 customerlistinfo.jsp 41 5.6.4 allinfo.jsp 41 5.7 收费厅管理模块 42 5.7.1 Left.jsp 42 5.7.2 Work.jsp 43 5.7.3 Customerlistinfo.jsp 43 5.7.4 gongdan.jsp 43 6 系统测试与维护 45 6.1 测试目的 45 6.2 测试环境 45 6.3 系统测试 45 6.4 系统维护 45 7 开发难点与技术 46 7.1 主要程序实现的代码描述 46 7.1.1 验证码的自动生成 46 7.1.2 生成WORD工单 46 7.1.3 以一定的时间刷新页面 47 7.1.4 JSP文问题的解决 47 7.2 在程序编码过程遇到的主要问题: 48 7.3 代码编写风格 49 7.4 我的不足: 49 结束语 50 致 谢 50

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值