表单开发.docx
- 文档编号:18555295
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:38
- 大小:1.32MB
表单开发.docx
《表单开发.docx》由会员分享,可在线阅读,更多相关《表单开发.docx(38页珍藏版)》请在冰点文库上搜索。
表单开发
表单开发流程与方法
朱建奎、赵雁
NC管理会计
2012.3.9
目录
一、预备知识2
1、数据结构2
基于数组和链表的List实现2
基于数组的快速排序原理2
2、Java的知识准备3
JTable渲染器3
事件处理机制4
泛型、可变参数、foreach循环5
3、数据库6
SQL:
结构化查询语言6
JDBC:
java数据库连接7
4、设计模式7
MVC7
观察者模式7
静态工厂方法模式8
二、开发流程9
1、实现ArrayList和LinkedList9
2、实现对List通用的快速排序12
3、实现基于订单号的快速排序14
4、建立数据库表和序列15
5、连接数据库,实现业务层逻辑15
6、设计图形界面18
7、实现从数据库中获取数据,并显示在界面中18
8、实现按钮间的相互关联19
9、各个按钮的功能实现23
10、实现表格的按列排序25
11、添加行头以及单元格的渲染26
12、应用MVC模式重构27
一、预备知识
1、数据结构
基于数组和链表的List实现
数组是一种物理存储单元上连续的、顺序的存储结构。
它是把具有相同类型的若干变量按有序的形式组织起来的一种形式,是按序排列的同类数据元素的集合,它的大小是不可变的。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:
一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比于线性表顺序结构,链表比较方便插入和删除操作。
基于数组的快速排序原理
其基本思想是:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
例子:
基于数组的递归实现的快速算法如下(下面代码中只用一种算法,另外一种算法详见代码):
privatestaticintpartition(int[]arr,intm,intn){
intkey=arr[m];
while(m while(m --n; } arr[m]=arr[n]; while(m ++m; } arr[n]=arr[m]; } arr[m]=key; returnm; } publicstaticvoidquickSort(int[]arr,intm,intn){ if(m intt=partition(arr,m,n); quickSort(arr,m,t-1); quickSort(arr,t+1,n); } } 2、Java的知识准备 JTable渲染器 采用JTable渲染器可以设置表格中单元格的颜色等,通过覆盖父类DefaultTableCellRenderer的getTableCellRendererComponent(JTabletable,Objectvalue,booleanisSelected,booleanhasFocus,introw,intcolumn)方法就可以自定义表格的样式。 比如: 1)可以设置表格的偶数行与奇数行显示的颜色; 2)选中单元格的颜色,获得焦点的颜色; 3)可以设置单元格中数据满足某一条件时进行高亮显示。 下图中是对订单数量大于或者等于80的突出显示: 事件处理机制 事件最初由事件源产生,事件源可以是GUI组件JavaBean或由生成事件能力的对象。 在GUI组件情况下,事件源可以是组件的同位体(相对于AbstractWindowToolkit[awt]GUI组件),也可以是组件本身(相对于Swing组件)。 事件生成后,放在系统事件队列内部。 此时,事件处于事件分发线程的控制下,在队列中等待处理。 当事件从队列中选出后,被送到dispatchEvent()方法中,dispatchEvent()方法调用processEvent()方法并将事件的一个引用传递给processEvent()方法。 此刻,系统会查看是否有送出事件的位置,如果没有这种事件类型相应的已经注册的监听器,或者如果没有任何组件受到激活来接收事件类型,事件就被抛弃。 当然上图显示的是AWTEvent类的子类的生命周期。 dispatchEvent()方法和processEvent()方法把AWTEvent作为一个参数。 但javax.swing.event并不是AWTEvent子类,而是从EventObject直接继承过来,生成这些事件的对象也会定义fireEvent()方法,此方法将事件送到包含在对象监听器列表内的那种类型的任何监听器。 泛型、可变参数、foreach循环 泛型是JDK1.5引入的新特性: 在java中,泛型的参数只可以代表类,不能代表个别对象。 由于Java泛型的类型参数的实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。 Java编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。 可变参数也是JDK1.5引入的新特性,它允许只定义一个方法。 在方法的定义中,参数是可变的,一般用“类型…变量名”来表示,它们三者之间的空格比较随意。 通过引入可变参数,可以只定义一个方法就可以达到代码的复用。 foreach语句是java5的新特征之一,在遍历数组、集合方面,foreach为开发人员提供了极大的方便。 foreach并不是一个关键字,习惯上将这种特殊的for语句格式称之为“foreach”语句。 从英文字面意思理解foreach也就是“for每一个”的意思。 实际上也就是这个意思。 foreach的语句格式: for(元素类型t元素变量x: 遍历对象obj){ 引用了x的java语句; } 例如下面的例子(用到了可变参数和foreach循环): publicclassTest{ publicstaticvoidmain(String[]args){ inta=4; intb=2; intc=3; print(a,b); System.out.println("***********|"); print(a,b,c); System.out.println("***********"); print(a); } privatestaticvoidprint(int...vars){//可变参数 for(inti: vars){ System.out.print(i+""); } System.out.println(); } } 3、数据库 SQL: 结构化查询语言 SQL 全名是结构化查询语言(StructuredQueryLanguage),是用于数据库中的标准数据查询语言,通过使用它,可以进行CRUD(增加(Create)、查询(Retrieve)(重新得到数据)、更新(Update)和删除(Delete))的操作。 JDBC: java数据库连接 JDBC(JavaDataBaseConnectivity,java数据库连接)是一种用于执行SQL语句的JavaAPI。 它可以为多种关系数据库提供统一访问,由一组用Java语言编写的类和接口组成。 JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。 4、设计模式 MVC MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller)。 MVC模式的目的就是实现Web系统的职能分工。 Model层实现系统中的业务逻辑,通常可以用JavaBean或EJB(EnterpriseJavaBean)来实现。 View层用于与用户的交互,通常用JSP来实现。 Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。 通过使用MVC设计模式,可以使三者解耦,使它们之间的模块独立性增强,这样就满足了单一职权原则,就更有利于代码的复用和维护。 图示如下: 观察者模式 观察者模式(Observer)完美的将观察者和被观察的对象分离开。 举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。 面向对象设计的一个原则是: 系统中的每个类将重点放在某一个功能上,而不是其他方面。 一个对象只做一件事情,并且将他做好。 观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。 图示如下: 静态工厂方法模式 静态工厂方法模式又称为简单工厂方法模式,它是由一个工厂对象决定创建出哪一种产品类的实例。 简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。 图示如下: 二、开发流程 1、实现ArrayList和LinkedList ArrayList是采用数组实现的,其内部封装了一个数组,是一个顺序存储结构;而LinkedList是基于链表的原理实现的,可以考虑在它的内部封装一个内部类,是一个链式存储结构。 由图上的方法getLength(),get(),isEmpty(),getPrevious(),getCurrent()等,可以考虑在ArrayList和LinkedList中设置size(表示的集合中元素的个数)和index(集合中元素的索引)的属性。 在集合中元素增添或者删除时,size能够进行相应的改变,index可以相当于该元素是集合中的第index+1个元素(index从零开始),因此关于getLength()和isEmpty()的方法可以实现如下: @Override publicintgetLength(){ returnsize; } @Override publicbooleanisEmpty(){ returnsize==0; } 1)关于ArrayList基于数组的相关方法的实现: 首先,ArrayList应该能够动态地改变数组的大小,在内部应该能够进行动态分配。 添加元素时,要保证数组的length不小于一个最小容量(即Size+1)。 倘若不满足这个条件,数组应该重新分配大小。 这里我们使它新分配的length增长为原来的1/2,实现代码如下: privatevoidensureCapacity(intminCapacity){ if(array.length intnewLen=(array.length*3)/2+1; array=Arrays.copyOf(array,newLen); } } 如上图所示,即为插入元素和删除元素的过程。 有了以上的基础,就可以实现add方法: publicbooleanadd(Ee){ ensureCapacity(size+1); array[size++]=e; returntrue; } 在删除一个元素时,它后面的所有元素都应该相应地前移一位,最后一个元素应该置null,同时元素的个数size减1,下面是delete(Ee)方法的实现代码: publicbooleandelete(Ee){ for(inti=0;i if(e.equals(array[i])){ System.arraycopy(array,i+1,array,i,array.length-1-i); array[array.length-1]=null; --size; returntrue; } } returnfalse; } 在获取索引为i的元素时,应该保证该索引在指定的范围,否则在取数组相应元素时会发生ArrayIndexOutOfBoundsException,下面是具体的实现: @Override publicEget(inti){ rangeCheck(i); return(E)array[i]; } privatevoidrangeCheck(inti){ if(i<0||i>size-1){ thrownewIllegalArgumentException("参数错误"); } } 在实现getPrevious()和getNext()方法时,我们应该先判断是否还有上一个或者下一个元素,若有相应元素才进行返回,下面以getNext()为例: @Override publicEgetNext(){ if(hasNext()){ return(E)array[++index]; } thrownewRuntimeException("已经是最后一个元素了"); } privatebooleanhasNext(){ returnindex } 2)LinkedList的相应部分实现如下: (主要应用的是单链表) 为了便于数据的处理,我们封装了一个内部类Node,并且拥有对下一个Node的引用: classNode{ privateNodenext; privateEe; publicNode(){ super(); } publicNode(Nodenext,Ee){ super(); this.next=next; this.e=e; } } 类似于数组的add和delete,链表也有增加和删除操作。 我们只给出单链表实现add和delete的原理图: 2、实现对List通用的快速排序 结合我们对数组进行快速排序的原理,我们可以对集合List进行快速排序,因为List中存放的是某一类型的对象,因此我们存放的对象必须实现Sortable接口。 因此我们定义的方法声明如下: publicstaticvoidquickSort(List extendsSortable>list){ } 为了能够达到通用的目的,我们重载了方法: privatestaticvoidquickSort(List extendsSortable>list,intm,intn){ …………………………………………………… } 并且在只有一个参数的方法中调用另外一个方法,即quickSort(list,0,list.getLength()-1);在实现中,我们不可避免地要为集合List中的某一个下标的对象重新赋值,因此为List接口增添了下列方法: Objectset(intm,Objectobj);并且在ArrayList和LinkedList中分别实现了该方法,下面是LinkedList中的实现: @Override publicObjectset(intm,Objectobj){ rangeCheck(m); Nodetmp=first; for(inti=0;i tmp=tmp.next; } Nodet=tmp; tmp.e=(E)obj; returnt.e; } privatevoidrangeCheck(intm){ if(m<0||m>size-1){ thrownewIllegalArgumentException("参数错误"); } } 采用数组的快速排序思想,List的快速排序就可以轻松实现了。 不同的是我们对整型数组元素比较时,应该调用compareTo方法。 3、实现基于订单号的快速排序 利用上一节知识,我们实现基于订单号(saleNo)的快速排序。 由于我们在List集合中存放了SaleOrder,因此SaleOrder应该实现Sortable接口。 部分代码如下: publicclassSaleOrderimplementsSortable ………………………… @Override publicintcompareTo(SaleOrdersaleOrder){ returnbillNo-saleOrder.billNo; } } 下面是我们对基于订单号的快速排序的测试: @Test publicvoidtestQuickSortListOfSortable(){ List SaleOrderso1=newSaleOrder(); SaleOrderso2=newSaleOrder(); SaleOrderso3=newSaleOrder(); so1.setBillNo (2); so2.setBillNo (1); so3.setBillNo(3); list.add(so1); list.add(so2); list.add(so3); printList(list); System.out.println("**************"); SortUtil.quickSort(list); printList(list); } privatevoidprintList(List for(inti=0;i System.out.println(list.get(i).getBillNo()); } } 4、建立数据库表和序列 先建立一个SaleOrder表,存放SaleOrder。 再建立一个序列,用以从序列中取得SaleOrder的主键。 脚本代码如下: createsequencemy_seq startwith1 incrementby1 minvalue1 cache100; createtablesale_order( bill_idnumberprimarykey, bill_nonumber, bill_datedate, productvarchar2(30), client_namevarchar2(15), current_typevarchar2(5), pricenumber(7,2), amountnumber, bill_numnumber(7,2), memovarchar2(50) ); 注: 上表中price中的7表示输入的字符不能超过7位,否则就异常了。 所以,在使用时请注意。 5、连接数据库,实现业务层逻辑 我们在实现DBUtil时,用到了ThreadLocal,涉及到了线程所以不建议使用。 DBUtil中定义了两个方法,一个是getConnection,另外一个是closeConnection,该工具类代码实现通常比较简单,就不再多说了。 下面是业务层的部分实现: @Override publicvoidinsert(SaleOrdersaleOrder){ Connectionconn=DBUtil.getConnection(); PreparedStatementps=null; Stringsql="insertintosale_ordervalues(? ? ? ? ? ? ? ? ? ? )"; try{ ps=conn.prepareStatement(sql); ps.setInt(1,getNextValueFromSequence()); ……………………………… ps.execute(); }catch(SQLExceptione){ e.printStackTrace(); }finally{ closeResourceIncludeConnection(null,ps); } } privatevoidcloseResourceIncludeConnection(ResultSetrs,PreparedStatementps){ closeResourceWithoutConnection(rs,ps); DBUtil.closeConnection(); } privatevoidcloseResourceWithoutConnection(ResultSetrs,PreparedStatementps){ if(rs! =null){ try{ rs.close(); }catch(SQLExceptione){ e.printStackTrace(); } } if(ps! =null){ …………………… } } 下面是对insert方法的测试以及在后面的界面中显示效果: @Test publicvoidtestInsert(){ for(inti=0;i<30;i++){ SaleOrdersaleOrder=newSaleOrder(); Randomrnd=newRandom(); saleOrder.setBillNo(1234*Math.abs(rnd.nextInt(100))); saleOrder.setBillDate(newDate()); saleOrder.setClientName(newString[]{"Jim","Mary","Tom","李雷","韩梅梅"}[rnd.nextInt(5)]); saleOrder.setCurrentType(newString[]{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 表单 开发