java swing 打地鼠游戏 按钮添加按钮单击事件件之后,运行完,怎么再按开始按钮使他恢复原状。

Java自学笔记(2/3)-菜鸟学编程,大牛请轻虐小站-人人小站
Java自学笔记(2/3)
继承:&&& 继承性是面向对象的重要特性。继承允许一个类成为另一个类的子类,子类继承了父类的所有特性,并且可以扩展出自己特征。类的继承性提供了一种明确描述共性的方法,减少了类似的重复说明。在Java 中任何一个类都有父类(除了object 类以外)。Java 只支持单重继承,大大降低了继承的复杂度。&
子类创建:&&& 一个类的后代可以继承它的祖先的所有变量和方法,就像自己创建的一样。一个类的子
类是它的继承了父类的成员变量和方法的特殊版本。创建子类的语法格式如下:
子类名extends 父类名&
null、this、super关键字:
I.&null 相当于&空&,可以用来代指任何对象,但没有实例。如:Rectangle r=创建了一个Rectangle 的变量r,但并没有一个Rectangle 的实例对象由r 来代表。r 就如同一个可放置Rectangle 的盒子,只是这个盒子现在是空的。
II.&this 用以指代当前的类的一个对象自身。它的作用主要是将自己这个对象作为参数,传送给别的对象中的方法。
III.&super&用来取用父类中的方法和变量数据。
IV.&super 和this 的另一个重要用途是用在构造函数中。当一个类中不止一个构造函数时,可以用this 在一个构造函数中调用另一个构造函数。若想调用父类的构造函数,则直接使用super。
实例分析:public class ext {&&& static class father {&&&&&&&&&&&&&& S&&&&&&& public father(int num, String name){&&&&&&&&&&& this.num=&&&&&&&&&&& this.name=& && }&&&&&&&&& public father(){&&&&&&&&&&& this(1,"father");& }&&&&&&&&&& // 给出父类的两种构造方法,其中father()方法通过this关键字调用了father(int num, String name)&&&&&&& void print(){&&&&&&&&&&& System.out.println("这是父类方法print(),打印父类对象内容:num="+this.num+";name="+this.name);&&&&&&& }&&& }&&& static class son extends father{&&&&&&& public son(int num, String name){&&&&&&&&&&& super(num, name);&&&&&&&&&& //&子类构造方法,通过super关键字调用了父类的构造方法&&&&&&& }&&&&&&& void print(){&&&&&&&&&& &&& &&&&&&& &&&// 重写了父类print()方法&&&&&&&&&&& System.out.print("这是子类方法print():");&&&&&&&&&&& super.print();&&&&&&& }&&& }&&& public static void main(String[] args) {&&&&&&& father f=new father();&&&&&&& f.print();&&&&&&& son s=new son(2,"son");&&&&&&& s.print();&&&& }}
多态:&&& 多态是指把类中具有相似功能的不同方法用同一个方法名来定义,从而可以使用相同的方式来调用这些具有不同功能的同名方法。Java 通过覆盖和重载来实现多态。&重载&是指同一样东西在不同的地方具有多种含义;而&覆盖&是指它随时随地都只有一种含义,只是原先的含义完全被后来的含义取代了。
I.方法覆盖:覆盖的意思是不用考虑父类的方法是如何写的,只要重新定义改写,就可以采用新的方法。
II.&方法重载:重载可理解为一个方法名有两个或两个以上的含义,即在Java 中,可以在同一个类中定义多个同名的方法。在方法重载时,根据方法参数的个数、类型、顺序来决定采用哪个方法。&
static关键字:&&& static关键字可用于修饰类的变量、方法和内部类。当声明一个事物是static时,就意味着这个域(可以理解为&static{}&之间的内容)或方法不会与包含static声明的事物的类的任何对象实例关联在一起,它只和整个域相关。所以,即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域。通常,您必须创建一个对象,并用它来访问数据和方法。是因为非static域或方法必须知道他们一起运作的特定对象(也就是说非static域或方法必须通过该类的对象来调用,因此非static域或方法不能访问或调用static域及static方法)。
I.静态方法:&&& 最常用的静态方法就是主方法public static void main(),Java语言面向对象的特点要求只有具体对象才能分配内存空间并访问或调用;但对于main方法,大部分情况下根本就没有具体对象,但我们仍要运行该方法,所以使用static关键字,即不需要该类的具体对象就可以调用该方法。通常,在一个类中定义一个方法为static,那就是说,用类名而无需本类的具体对象即可调用此方法,即class.doSth();因为static方法与具体对象无关,它只与所在的类这个整体概念相关。
II.静态变量:&&&&所有此类实例共享此static变量,也就是说在类装载时,只分配一块存储空间,所有此类的具体对象都可以操控此块存储空间(static变量有点类似于C中的全局变量的概念)。例如计算圆面积时编写一个class Round,圆半径r、面积s是其成员变量,圆周率pi就可以声明为static变量,即便没有创建Round类的具体对象,也应该事先给pi分配储存空间,这样可以在没有对象的情形下修改其精度,同时,不同的Round对象中成员变量pi都指向同一段内存空间(一个static字段对每个类来说都只有一份的存储空间,而非static字段则是对每个对象都有一个存储空间)。一个实例对象中的成员变量按照先static后非static变量初始化的顺序开始初始化各个变量。
III.静态(内部)类:&&& 通常一个普通类不允许声明为静态的,只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用,而不需实例一个外部类。但static的内部类不能再使用外部类的非static成员。例如在外部类的外部,要生成(new)一个内部类对象,需要首先建立一个外部类对象(外部类可用),然后在生成一个内部类对象。   即:Outer o=new Outer();Outer.Inner in=o.new.Inner();但静态内部类就可以在外部直接生成对象:Outer.Inner in=new Outer.Inner();又如上面实例分析中的father是静态内部类,因此可以直接在main方法中生成对象f。&
java.awt包:抽象窗口工具包AWT (Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可用于Java的applet和applications中。java.awt包提供了基本的java程序的GUI设计工具主要包括下述三个概念:组件(Component)、容器(Container)、布局管理器(LayoutManager)。
组件:&&& Java的图形用户界面的最基本组成部分是组件(Component),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,例如一个按钮,一个标签等。组件不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。类ponent是许多组件类的父类,Component类中封装了组件通用的方法和属性,如图形的组件对象、大小、显示位置、前景色和背景色、边界、可见性等,因此许多组件类也就继承了Component类的成员方法和成员变量,相应的成员方法包括:   getComponentAt(int x, int y)   getFont()   getForeground()   getName()   getSize()   paint(Graphics g)&
容器(Container)实际上是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,但是它的主要功能是容纳其它组件和容器。一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。容器分三类:Window、Panel、ScrollPane。常用容器有以下几种:
I.Frame:&&& java.awt.Frame是java.awt.Window的子类,一般要生成一个窗口,通常是用Window的子类Frame来进行实例化,而不是直接用到Window类。每个Frame的对象实例化以后都是没有大小和不可见的,因此必须调用setSize( )来设置大小,调用setVisible(true)来设置该窗口为可见的。另外,Frame是一个顶级窗口。
II.Panel:&&& java.awt.Panel是java.awt.Container的子类,是一种最简单的容器,提供空间将组件附于其上,一个Frame可以容纳多个Panel。Panel无法单独显示,必须加入到别的容器中。&
布局管理器:&&& java为了实现跨平台的特性并且获得动态的布局效果,将容器内的所有组件安排给一个"布局管理器"负责管理。用户无法在这种情况下设置组件的这些属性,如果试图使用Java 语言提供的setLocation(),setSize(),setBounds() 等方法,则都会被布局管理器覆盖。 如果用户确实需要亲自设置组件大小或位置,则应用setLayout(null);禁用布局管理器。使用setLayout(new ***Layout());可以调用并设置布局管理器。布局管理器有多种,常用的几种如下:
I.&FlowLayout:&&& 最简单的布局管理器,Panel、Applet的缺省布局管理器。组件的放置规律是从上到下、从左到右进行放置,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。
II.&BorderLayout:&&& Window,Frame和Dialog的缺省布局管理器。BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。各个区域的位置及大小如下图所示:
III.&GridLayout:使容器中各个组件呈网格状布局,平均占据容器的空间。
IV.&CardLayout:&&& CardLayout布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,它把容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件,当然每层都可以利用Panel来实现复杂的用户界面。牌布局管理器(CardLayout)就象一副叠得整整齐齐的扑克牌一样,有54张牌,但是你只能看见最上面的一张牌,每一张牌就相当于牌布局管理器中的每一层。
AWT事件处理:&&& 在事件处理的过程中,主要涉及三类对象:  ◇&Event-事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。  ◇&Event Source-事件源,事件发生的场所,通常就是各个组件,例如按钮Button。& & & &◇&Event handler-事件处理者,接收事件对象并对其进行处理的对象。由于同一个事件源上可能发生多种事件,因此java采取了授权处理机制(Delegation Model),事件源可以把在其自身所有可能发生的事件分别授权给不同的事件处理者来处理。有时也将事件处理者称为监听器,主要原因也在于监听器时刻监听着事件源上所有发生的事件类型,一旦该事件类型与自己所负责处理的事件类型一致,就马上进行处理。授权模型把事件的处理委托给外部的处理实体进行处理,实现了将事件源和监听器分开的机制。监听器通常是一个类,该类如果要能够处理某种类型的事件,就必须实现与该事件类型相对的接口。使用授权处理模型进行事件处理的一般方法归纳如下:&I.对于某种类型的事件XXXEvent, 要想接收并处理这类事件,必须定义相应的事件监听器类,该类需要实现与该事件相对应的接口XXXListener;II.事件源实例化以后,必须进行授权,注册该类事件的监听器,使用addXXXListener(XXXListener ) 方法来注册监听器。&
AWT事件类:&&&&与AWT有关的所有事件类都由java.awt.AWTEvent类派生,它也是EventObject类的子类。AWT事件共有10类,可以归为两大类:低级事件和高级事件。低级事件是指基于组件和容器的事件,高级事件是基于语义的事件,它可以不和特定的动作相关联,而依赖于触发此事件的类。
&&&&◇ 低级事件  ComponentEvent( 组件事件:组件尺寸的变化,移动)  ContainerEvent( 容器事件:组件增加,移动)  WindowEvent( 窗口事件:关闭窗口,窗口闭合,图标化)  FocusEvent( 焦点事件:焦点的获得和丢失)  KeyEvent( 键盘事件:键按下、释放)&  MouseEvent( 鼠标事件:鼠标单击,移动)
& &◇ 高级事件(语义事件)  ActionEvent(动作事件:按钮按下,TextField中按Enter键)  AdjustmentEvent(调节事件:在滚动条上移动滑块以调节数值)  ItemEvent(项目事件:选择项目,不选择"项目改变")& & & &TextEvent(文本事件,文本对象改变)&
AWT监听器接口:&&& 每类事件都有对应的事件监听器,监听器是接口,根据动作来定义方法。这些抽象方法应该在用户使用的监听器类中予以实现。例如,与键盘事件KeyEvent相对应的接口是:  public interface KeyListener extends&EventListener&{     public void keyPressed(KeyEvent ev);     public void keyReleased(KeyEvent ev);     public void keyTyped(KeyEvent ev);} // 其中有三个抽象方法,分别对应于按键被按下、被松开以及被敲击一次的事件。所有的监听器接口都继承了EventListener类
AWT的组件类中提供注册和注销监听器的方法:◇ 注册监听器:  public void add&ListenerType& (&ListenerType&listener);◇ 注销监听器:  public void remove&ListenerType& (&ListenerType&listener);&
AWT适配器类:&&& Java语言为一些Listener接口提供了适配器(Adapter)类。可以通过继承事件所对应的Adapter类,只重写需要方法,无关方法不用实现。事件适配器为我们提供了一种简单的实现监听器的手段, 可以缩短程序代码。实际上,适配器类可以看做简化的、定制的监听器类,即只实现所需的方法。但由于java的单一继承机制,当需要多种监听器或此类已有父类时,就无法采用事件适配器了。&&& 适配器类的例子如下:public class MouseClickHandler extends MouseAdaper{    public void mouseClicked(MouseEvent e) //只实现需要的方法       { &&}}
java.awt.event包中定义的事件适配器类包括以下几个:1.ComponentAdapter( 组件适配器)2.ContainerAdapter( 容器适配器)3.FocusAdapter( 焦点适配器)&4.KeyAdapter( 键盘适配器)&5.MouseAdapter( 鼠标适配器)&6.MouseMotionAdapter( 鼠标运动适配器)7.WindowAdapter( 窗口适配器)
在实际编程中,实现事件监听器时,往往采用内部类、匿名类进行编程。&&
个税计算器:import java.awt.*;import java.awt.event.*;import java.text.*;public class Income extends MouseAdapter implements ActionListener{&&& F&&& Label& lb,new_lb,old_lb,&&& TextField tf,new_result,old_&&& B&&& Panel p1,p2,p3;&&& public static void main(String[] args) {&&&&&&& Income a=new Income();&&&&&&& a.init();&&& }&&& public void init(){&&&&&&& f=new Frame("个税计算器v1.0 &&&&&&& by sunxb");&&&&&&& p1=new Panel();&&&&&&& p2=new Panel();&&&&&&& f.setSize(500,200);&&&&&&& f.setVisible(true);&&&&&&& f.setLayout(new BorderLayout());&&&&&&& f.add("Center",p1);&&&&&&& f.add("South",p2);&&&&&&& p1.setLayout(new GridLayout(3,2,20,7));&&&&&&& lb=new Label("请输入您的薪金收入(元)并按回车键确认:");&&&&&&& tf=new TextField(10);&&&&&&& new_lb=new Label("按照新的个税税率,您需缴纳个税(元):");&&&&&&& new_result=new TextField(10);&&&&&&& old_lb=new Label("按照旧的个税税率,您需缴纳个税(元):");&&&&&&& old_result=new TextField(10);&&&&&&&&& cmp=new Label("新旧个税比较:");&&&&&&& p1.add(lb);&&&&&&& p1.add(tf);&&&&&&& p1.add(new_lb);&&&&&&& p1.add(new_result);&&&&&&& p1.add(old_lb);&&&&&&& p1.add(old_result);&&&&&&& exit=new Button("退出");&&&&&&& p2.setLayout(new GridLayout(2,1,2,3));&&&&&&& p3=new Panel();&&&&&&& p2.add(cmp);&&&&&&& p2.add(p3);&&&&&&& p3.add(exit);&&&&&&& exit.addMouseListener(this);&&&&// exit按钮注册Mouse事件监听器,this表示使用Income类的对象a的监听器(Income类本身已经继承了MouseAdapter、实现了ActionListener)&&&&&&& tf.addActionListener(this);&&&&&// tf文本框注册Action事件监听器&&& }&&&&public void actionPerformed(ActionEvent te){&&&&// 实现actionPerformed方法,对应于用户在文本框中输入薪金之后敲击回车的事件&&&&&&& double new_tax=0,old_tax = 0,wage=0;&&&&&&& DecimalFormat& myformat=new DecimalFormat("#0.00"); &&& // 设定浮点数显示精度为两位小数&&&&&&& wage=Double.parseDouble(tf.getText());&&&&&&& double _new_=wage-3500;&&&&&&& double _old_=wage-2000;&&&&&&& if(wage&0) {&&&&&&&&&&& new_result.setText("您输入的数据有误,请重新输入!");&&&&&&&&&&& &&&&// 数据有效性检查,避免无效数据进入运算。如果用户输入的薪金小于0,则直接返回,不再执行以下运算,同时打印提示信息。&&&&&&& }&&&&&&& if(_new_&0) new_tax=0;&&&&&&& if(_new_&=0&&_new_&1500)&&& & new_tax=_new_*0.03;&&&&&&& if(_new_&=1500&&_new_&4500) & new_tax=_new_*0.10-105;&&&&&&& if(_new_&=4500&&_new_&9000) & new_tax=_new_*0.20-555;&&&&&&& if(_new_&=9000&&_new_&35000)&&& & new_tax=_new_*0.25-1005;&&&&&&& if(_new_&=35000&&_new_&55000)&& & new_tax=_new_*0.30-2755;&&&&&&& if(_new_&=55000&&_new_&80000)&& & new_tax=_new_*0.35-5505;&&&&&&& if(_new_&=80000)&&& & new_tax=_new_*0.45-13505;&&&&&&& if(_old_&0) old_tax=0;&&&&&&& if(_old_&=0&&_old_&500) old_tax=_old_*0.05;&&&&&&& if(_old_&=500&&_old_&2000)& old_tax=_old_*0.10-25;&&&&&&& if(_old_&=2000&&_old_&5000) old_tax=_old_*0.15-125;&&&&&&& if(_old_&=5000&&_old_&20000)&&& old_tax=_old_*0.20-375;&&&&&&& if(_old_&=20000&&_old_&40000)&& old_tax=_old_*0.25-1375;&&&&&&& if(_old_&=40000&&_old_&60000)&& old_tax=_old_*0.30-3375;&&&&&&& if(_old_&=60000&&_old_&80000)&& old_tax=_old_*0.35-6375;&&&&&&& if(_old_&=80000&&_old_&100000)& old_tax=_old_*0.40-10375;&&&&&&& if(_old_&=100000)&& old_tax=_old_*0.45-15375;&&&&&&& new_result.setText(myformat.format(new_tax));&&&&&&& old_result.setText(myformat.format(old_tax));&&&&&&& if(new_tax&old_tax) cmp.setText("新旧个税比较:按照新税率,你将比原来多缴纳税款"+(new_tax-old_tax)+"元。");&&&&&&& if(new_tax&old_tax) cmp.setText("新旧个税比较:按照新税率,你将比原来少缴纳税款"+(old_tax-new_tax)+"元。");&&&&&&& if(new_tax==old_tax)&&& cmp.setText("新旧个税比较:按照新税率,你所缴纳的税款与原来一样。");&&&&&&& }&&&&public void mouseClicked(MouseEvent me){&&&&// 实现mouseClicked方法,对应于用户在点击退出按钮的事件&&&&&&& System.exit(0);&&& }}
&事实上,个税计算中大量使用的税率、起征点、速算扣除数最好用常数变量表示,例如final double rate1=0.05;这样可提高程序的灵活性和可读性。&
线程与进程:&&& 一般可以在同一时间内执行多个程序的操作系统都有进程的概念。一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间、一组系统资源。在进程概念中,每一个进程的内部数据和状态都是完全独立的。Java程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程被称为轻负荷进程(light-weight process,轻量级进程)。一个进程中可以包含多个线程。&&& Java内在支持多线程,它的所有类都是在多线程下定义的,Java利用多线程使整个系统成为异步系统。Java中的线程由三部分组成:  I、虚拟的CPU,封装在java.lang.Thread类中。  II、CPU所执行的代码,传递给Thread类。
& & & &III、CPU所处理的数据,传递给Thread类。&
Thread类与线程体:Java的线程是通过java.lang.Thread类来实现的。当我们生成一个Thread类的对象之后,一个新的线程就产生了。同其他类类似,Thread提供了如下构造方法:
public Thread&(ThreadGroup group,Runnable target,String name);
如此声明和构造的线程实例表示Java解释器中的真正的线程,通过它可以启动线程、终止线程、线程挂起等,每个线程都是通过类Thread在Java的软件包Java.lang中定义的。
一个类声明实现Runnable接口就可以充当线程体,在接口Runnable中只定义了一个方法 run():
public void run();任何实现接口Runnable的对象都可以作为一个线程的目标对象,类Thread本身也实现了接口Runnable。每个线程都是通过某个特定Thread对象的方法run( )来完成其操作的,因此方法run()就称为线程体。实现一个线程体的方法:
I.&定义一个线程类,它继承线程类Thread并重写其中的方法 run();
II.&提供一个实现接口Runnable的类作为一个线程的目标对象target;&
线程的状态:
&&& I.&创建状态(new Thread)  执行下列语句时,线程就处于创建状态:  Thread myThread = new MyThreadClass( );当一个线程处于创建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。
& & II.&可运行状态( Runnable )& & & myThread.start( );当一个线程处于可运行状态时,系统为这个线程分配了它需的系统资源,安排其运行并调用线程运行方法,这样就使得该线程处于可运行( Runnable )状态。
& & III.&不可运行状态(Not Runnable)进入不可运行状态的原因有如下几条:  1) 调用了sleep()方法;  2) 调用了suspend()方法;  3) 为等候一个条件变量,线程调用wait()方法;  4) 输入输出流中发生线程阻塞;
& & IV.&死亡状态(Dead) 线程的终止一般可通过两种方法实现:自然撤消(线程执行完)或是被停止(调用stop()方法)。不建议使用stop()方法,因为存在固有安全性问题,新的jdk中已经抛弃了stop()方法。
数字时钟(applet):import java.applet.*;import java.awt.*;import java.util.*;public class clock extends Applet implements Runnable{&&& Thread clockThread=new Thread(this,"clock");&&&&&&& public void start(){&&&&&&&&&&& clockThread.start();&&&&&&& }&&&&&&& public void run(){&&&&&&&&&&& while(true){&&& // 无限循环,反复刷新&&&&&&&&&&& repaint();& // 刷新画面,此方法将自动调用下面的paint(Grahpics g)&&&&&&&&&&& try{&&&&&&&&&&&&&&& clockThread.sleep(1000);&&//&休眠1000毫秒(即1秒)后再次刷新&&&&&&&&&&& &}catch(InterruptedException ie) {System.out.println("线程错误!");}&&&&&&& & }&&&&&&& }&&&&&&& public void paint(Graphics g){&&&&&&&&&&& GregorianCalendar now=new GregorianCalendar();& & & & & & & & & & & & &g.drawString(now.get(Calendar.HOUR_OF_DAY)+":"+now.get(Calendar.MINUTE)+":"+now.get(Calendar.SECOND), 10, 20);&&&&&&& }}
html文件:&html&&applet &code=clock.class &width=150 &height=50&&/applet&&/html&&
Swing的基本概念:&&& AWT是Swing的基础。Swing的产生主要原因就是AWT不能满足图形化用户界面发展的需要。Swing组件几乎都是轻量组件,与重量组件相比,没有本地的对等组件,不像重量组件要在它们自己的本地不透明窗体中绘制,轻量组件在它们的重量组件的窗口中绘制。由于AWT组件通过与具体平台相关的对等类(Peer)实现,因此Swing比AWT组件具有更强的实用性。Swing在不同的平台上表现一致,并且有能力提供本地窗口系统不支持的其它特性。&&& 在javax.swing包中,定义了两种类型的组件:顶层容器(JFrame、JApplet、JDialog和JWindow)和轻量级组件。Swing组件都是AWT的Container类的直接子类和间接子类。swing包是Swing提供的最大包,它包含将近100个类和25个接口,几乎所有的Swing组件都在swing包中,只有JtableHeader和JtextComponent是例外,它们分别在swing.table和swing.text中。轻量级组件 是用JAVA代码画出来的,这样具有平台移植性。重量级组件是调用操作系统的函数画出来的组件。比如主窗体一般来说尽量用轻量级的组件,这样对程序的移植性很好,一般javax.swing包里的组件大部分是轻量级的java.awt里面的是重量级的。Swing是AWT的扩展,它提供了许多新的图形界面组件。Swing组件以&J&开头,除了有与AWT类似的按钮(JButton)、标签(JLabel)、复选框(JCheckBox)、菜单(JMenu)等基本组件外,还增加了一个丰富的高层组件集合,如表格(JTable)、树(JTree)。Swing的事件处理模型和具体方式与AWT一致。&
Swing与MVC:&&&&Swing采用了MVC的设计范式,即"模型-视图-控制"(Model-View-Controller),在一个MVC用户界面中有三个通讯对象:模型、视图和控件。模型是指定的逻辑表示法,视图是模型的可视化表示法,而控件则指定了如何处理用户输入。当模型发生改变时,它会通知所有依赖它的视图,视图使用控件指定其相应机制。为了简化组件的设计工作,在Swing组件中视图和控件两部分合为一体。每个组件有一个相关的分离模型和它使用的界面(包括视图和控件)。组件的模型通常是自动设置的,但通过Model类的子类或通过实现适当的接口也可以为组件建立自己的模型。把数据模型与组件联系起来用setModel( )方法。MVC是现有的编程语言中制作图形用户界面的一种通用的思想,其思路是把数据的内容本身和显示方式分离开,这样就使得数据的显示更加灵活多样。&
Swing组件分类:
Swing组件从功能上分可分为:  1) 顶层容器:JFrame、JApplet、JDialog、JWindow共4个  2) 中间容器:JPanel、JScrollPane、JSplitPane、JToolBar   3) 特殊容器:在GUI上起特殊作用的中间层,如JInternalFrame、JLayeredPane、JRootPane  4) 基本控件:实现人际交互的组件,如Jbutton、 JComboBox,、JList、JMenu、JSlider、 JtextField  5) 不可编辑信息的显示:向用户显示不可编辑信息的组件,例如JLabel、JProgressBar、 ToolTip6) 可编辑信息的显示:向用户显示能被编辑的格式化信息的组件,如JColorChooser、 JFileChoose、JFileChooser、Jtable、JtextAreaJComponent是一个抽象类,用于定义所有子类组件的一般方法。JComponent类继承于Container类,所以凡是此类的组件都可作为容器使用。JComponent类的特殊功能又分为:1) 边框设置:使用setBorder()方法可以设置组件外围的边框,使用一个EmptyBorder对象能在组件周围留出空白。2) 双缓冲区:使用双缓冲技术能改进频繁变化的组件的显示效果。与AWT组件不同,JComponent组件默认双缓冲区,不必自己重写代码。如果想关闭双缓冲区,可以在组件上施加setDoubleBuffered(false)方法。3) 提示信息:使用setTooltipText()方法,为组件设置对用户有帮助的提示信息。4) 键盘导航:使用registerKeyboardAction( )方法,能使用户用键盘代替鼠标来驱动组件。JComponent类的子类AbstractButton还提供了便利的方法&&用setMnemonic( )方法指明一个字符,通过这个字符和一个当前L&F的特殊修饰共同激活按钮动作。5) 可插入L&F:每个Jcomponent对象有一个相应的ComponentUI对象,为它完成所有的绘画、事件处理、决定尺寸大小等工作。 ComponentUI对象依赖当前使用的L&F,用UIManager.setLookAndFeel( )方法可以设置需要的L&F。6) 支持布局:通过设置组件最大、最小、推荐尺寸的方法和设置X、Y对齐参数值的方法能指定布局管理器的约束条件,为布局提供支持。&
Swing组件的添加:&&& 与AWT组件不同,Swing组件不能直接添加到顶层容器中,它必须添加到一个与Swing顶层容器相关联的内容面板(content pane)上。内容面板是顶层容器包含的一个普通容器,它是一个轻量级组件。基本规则如下:  (1)把Swing组件放入一个顶层Swing容器的内容面板上(2)避免使用非Swing的重量级组件。
对顶层容器JFrame添加组件有两种方式:1) 用getContentPane()方法获得JFrame的内容面板,再对其加入组件:frame.getContentPane().add(childComponent)2) 建立一个Jpanel或 JDesktopPane之类的中间容器,把组件添加到容器中,用setContentPane()方法把该容器置为JFrame的内容面板:   Jpanel contentPane=new Jpanel( );   &&//把其它组件添加到Jpanel中;   frame.setContentPane(contentPane);
   //把contentPane对象设置成为frame的内容面板
常用的Swing容器及组件:
1.Jbutton:JButton 类继承自Abstract Button 类,主要是作为一个按钮,当此按钮被按下时便会产生动作事件而去执行程序所提供的处理此事件的方法。
2.JLabel:用来放置文字的类,主要是用来显示单行文字信息。同Jbutton一样,JLabel也有getText()、setText()方法。
3.JTextField:JTextField 提供单行文字编辑的功能。
4.JRadioButton:定义一群互斥的选取方法,也就是在同一群组的选项中只能有一个被选取。
5.JCheckBox:一般而言,对于JCheckBox 组件,它有两种状态可以被选择,主要是用在多重选项群组中。
6. JComboBox:下拉式选项列表组件,用来提供一个显示菜单,即每次只能选择其中的一项,但是可编辑每项的内容,而且每项的内容可以是任意类,而不再局限于String。
7. JFileChooser:JFileChooser用于选取文件并执行相关操作,内建有&打开&、&存储&两种对话框,还可以自己定义其他种类的对话框。
8. JList:适用于数量较多的选项以列表形式显示,里面的项目可以由任意类型对象构成。支持单选和多选。
9. JMenu:JMenu与AWT的菜单Menu的不同之处是它可以通过setJMenuBar(menubar)将菜单放置到容器中的任意地方。
10. JProgressBar:进程条是提供一个直观的图形化的进度描述,从"空"到"满"的过程。
11. JSlider:滑动条使得用户能够通过一个滑块的来回移动来输入数据。
12. JTable:表格是Swing新增加的组件,主要功能是把数据以二维表格的形式显示出来。使用表格,依据MVC的思想,最好先生成一个MyTableModel类型的对象来表示数据,这个类是从AbstractTableModel类中继承来的,其中有几个方法是一定要重写,例如getColumnCount,getRowCount,getColumnName,getValueAt。因为Jtable会从这个对象中自动获取表格显示所必需的数据,AbstractTableModel类的对象负责表格大小的确定(行、列)、内容的填写、赋值、表格单元更新的检测等等一切跟表格内容有关的属性及其操作。JTable类生成的对象以该TableModel为参数,并负责将TableModel对象中的数据以表格的形式显示出来。
13. JTree:如果要显示一个层次关系分明的一组数据,用树状图表示能给用户一个直观而易用的感觉,JTree类如同Windows的资源管理器的左半部,通过点击可以"打开"、"关闭"文件夹,展开树状结构的图表数据。JTree也是依据MVC的思想来设计的,Jtree的主要功能是把数据按照树状进行显示,其数据来源于其它对象。
Swing的布局管理器:
在Swing中设置布局管理器是针对于内容面板的,另外Swing新增加了一个BoxLayout布局管理器。BoxLayout布局管理器按照自上而下(y轴)或者从左到右(x轴)的顺序布局依次加入组件。建立一个BoxLayout对象,必须指明两个参数:被布局的容器和BoxLayout的主轴。缺省情况下,组件在纵轴方向上居中对齐。设置布局管理器的方法如下:pane.setLayout(new BoxLayout(pane,BoxLayout.Y-AXIS));其显示效果如下图示:
例1、打地鼠(极简版):import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.*;public class Hamster implements ActionListener{&&& JF&&& JPanel p1,p2,p3;&&& JS&&& JButton exit,&&& JButton[]&&& JLabel rst,&&&&&&&&& int total=0,click=0;&&& public static void main(String[] args) {&&&&&&& Hamster hm=new Hamster();&&&&&&& hm.init();&&&&&&& hm.play();&&&& }&&& public void init(){&&&&&&& f=new JFrame("打地鼠极简版&&&&& by sunxb");&&&&&&& f.setVisible(true);&&&&&&& f.setLayout(new BorderLayout());&&&&&&& f.setSize(800, 600);&&&&&&& p1=new JPanel();&&&&&&& p2=new JPanel();&&&&&&& f.getContentPane().add("North",p1);&&&&&&& f.getContentPane().add("Center",p2);&&&&&&& p1.setLayout(new GridLayout(2,1));&&&&&&& p3=new JPanel();&&&&&&& s=new JSlider(2,6);&&&&&&&&&&&&&&&&&&&& //& 设置滑动条的数值范围&&&&&&& hint=new JLabel("滑动滑块可调整&地鼠&出现的时间间隔:");&&&&&&& p1.setLayout(new GridLayout(3,1));&&&&&&& p1.add(hint);&&&&&&& p1.add(s);&&&&&&& p1.add(p3);&&&&&&& rst=new JLabel("&&&&&&&&&&&&&& ");&&&&&&& exit=new JButton("退出游戏");&&&&&&& rbg=new JButton("清除记录");&&&&&&& rst.setText("成绩:0 / 0&&& &&&&&&&&&&");&&&&&&& p3.add(rst);&&&&&&& p3.add(exit);&&&&&&& p3.add(rbg);&&&&&&& p2.setLayout(new GridLayout(6,6));&&&&&&& h=new JButton[36];&&&&&&&&& //& 用按钮作为被打击的&地鼠&&&&&&&& for(index=0;index&36;index++){&&&&&&&&&&& h[index]=new JButton("Click!");&&&&&&&&&&& h[index].addActionListener(this);&&&&&&&&&& //& 给&地鼠&注册监听器&&&&&&&&&&& p2.add(h[index]);&&&&&&&&&&& h[index].setVisible(false);&&&&&&&& //& 初始设置所有的&地鼠&均不可见且不可用(即不可点击)&&&&&&&&&&& h[index].setEnabled(false);&&&&&&& }&&&&&&& rbg.addActionListener(this);&&&&&&& //& 给&清除记录&按钮注册监听器&&&&&&& exit.addActionListener(this);&&&&&& //& 给&退出游戏&按钮注册监听器&&& }&&& public void play(){&&&&&&& Random rm=new Random(new GregorianCalendar().getTimeInMillis());&&&&&&&&&& //& 用格里高利历中当前时间与历元(GMT& 日00:00:00.000)之间的毫秒数做种生成随机数&&&&&&& while(true){&&&&&&&&&&& index=rm.nextInt(36);&&&&&& //& 生成0~35之间的某个整数(包括0和35,不包括36)&&&&&&&&&&& h[index].setVisible(true);& //& 将此随机选取的&地鼠&设置为可见并可用&&&&&&&&&&& h[index].setEnabled(true);&&&&&&&&&&& total++;&&&&&&& //& 记录出现的&地鼠&总数&&&&&&&&&&& t=s.getValue();&&&& //& 获取滑块对应的值&&&&&&&&&&& if(t==2) && s.setToolTipText("骨灰级!!(0.30秒)");&&&&&&&&&&& if(t==3)&&& s.setToolTipText("十足高手~~(0.45秒)");&&&&&&&&&&& if(t==4)&&& s.setToolTipText("不错不错^_^(0.60秒)");&&&&&&&&&&& if(t==5)&&& s.setToolTipText("略显迟钝-_-!(0.75秒)");&&&&&&&&&&& if(t==6)&&& s.setToolTipText("帕金森症患者╮(╯﹏╰)╭(0.90秒)");&&&&&&&&&&& //& 设置滑动条的光标提示信息(光标放在滑块上时将显示这些信息,滑块位置不同,显示信息也不同)&&&&&&&&&&& try{&&&&&&&&&&&&&&& Thread.currentThread();&&&&&&&&&&&&&&& Thread.sleep(150*t);&&&&&&&&&&&&&&&&&&& //& 利用线程休眠的方法实现延时(sleep是Thread类的静态方法)&&&&&&&&&&& }catch(InterruptedException e){System.exit(0);};&&&&&&&&&&& rst.setText("成绩:"+String.valueOf(click)+" / "+String.valueOf(total)+"&&&&&&&&&&&&& ");&&&&&&&&&&&&& h[index].setVisible(false);&&&& //& 延时完毕,&地鼠&再次&消失&&&&&&&&&&&& h[index].setEnabled(false);&&&&&&& }&&&&&&&&& }&&& public void actionPerformed(ActionEvent e) {&&&&&&& String order=e.getActionCommand();&&&&&&& if(order.equalsIgnoreCase("清除记录")){&&&&&&&&&&& click=0;&&&&&&&&&&& total=0;&&&&&&& }&&&&&&& if(order.equalsIgnoreCase("退出游戏")) System.exit(0);&&&&&&& if(order.equalsIgnoreCase("Click!")){&&&&&&&&&&& click++;&&&&&&&&&&& //& 记录打到的&地鼠&总数&&&&&&&&&&& JButton b=(JButton)e.getSource();&&&&&& //& 获取被打到的&地鼠&对象&&&&&&&&&&& b.setVisible(false);&&&&&&& //& &地鼠&被打后立即消失&&&&&&&&&&& b.setEnabled(false);&&&&&&& }&&& }}
例2、学分绩计算器:import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.text.*;import java.util.*;public class GPA implements ActionListener{&&& JF&&& JLabel info,index_lb,score_lb,credit_lb,&&& JButton cal, exit,&&& JPanel p2,p3,&&& JScrollP&&& ArrayList&JLabel& index_&&&&&&&&&& //& 课程数目不确定,不能使用常用的静态数组,因此改用ArrayList实现&&& ArrayList&JTextField& score_&&& ArrayList&JTextField& credit_&&& GridL&&& DecimalFormat& format_1;&&& double total_credit=0,credit_score=0,total_gpa=0;&&& public static void main(String[] args) {&&&&&&& new GPA().go();&&& }&&& public void go(){&&&&&&& f=new JFrame("学分绩计算器&&&& by sunxb");&&&&&&& f.setVisible(true);&&&&&&& f.setLayout(new BorderLayout());&&&&&&& f.setSize(350,500);&&&&&&& info=new JLabel("请输入各课程的成绩与学分,之后点击&开始计算&。");&&&&&&& p2=new JPanel();&&&&&&& p3=new JPanel();&&&&&&& table=new JPanel(); & &&&&&&&& scroll=new JScrollPane(table,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);&&&&&&& //& 由于课程数目不确定,因此要使用滚动面板ScrollPane方便查看&&&&&&& f.getContentPane().add("North",info);&&&&&&& f.getContentPane().add("Center",scroll);&&&&&&& f.getContentPane().add("South",p2);&&&&&&& gl=new GridLayout(13,3);&&&&&&&&&&& //& 默认值是12门课程,加上标题一共13行&&&&&&& table.setLayout(gl);&&&&&&& index_lb=new JLabel("序号");&&&&&&& score_lb=new JLabel("成绩");&&&&&&& credit_lb=new JLabel("学分");&&&&&&& table.add(index_lb);&&&&&&& table.add(score_lb);&&&&&&& table.add(credit_lb);&&&&&&& index_list=new ArrayList&JLabel&(gl.getRows()-1);&&&&&&& score_list=new ArrayList&JTextField&(gl.getRows()-1);&&&&&&& credit_list=new ArrayList&JTextField&(gl.getRows()-1);&&&&&&& for(int i=0;i&gl.getRows()-1;i++){&&&&& //& 向table中添加相应组件&&&&&&&&&&& index_list.add(new JLabel(String.valueOf(i+1)));&&&&&&&&&&& table.add(index_list.get(i));&&&&&&&&&&& score_list.add(new JTextField(3));&&&&&&&&&&& table.add(score_list.get(i));&&&&&&&&&&& credit_list.add(new JTextField(3));&&&&&&&&&&& table.add(credit_list.get(i));&&&&&&& }&&&&&&& gpa=new JLabel();&&&&&&& p2.setLayout(new GridLayout(2,1));&&&&&&& p2.add(gpa);&&&&&&& p2.add(p3);&&&&&&& cal=new JButton("开始计算");&&&&&&& addon=new JButton("增加课程");&&&&&&& exit=new JButton("退出程序");&&&&&&& p3.add(cal);&&&&&&& p3.add(addon);&&&&&&& p3.add(exit);&&&&&&& f.revalidate();&&&&&&& cal.addActionListener(this);&&&&&&& addon.addActionListener(this);&&&&&&& exit.addActionListener(this);&&&&&&& format_1=new DecimalFormat("#0.00");&&&&&&& //& 设置学分绩显示格式为带两位小数&&& }&&& public void actionPerformed(ActionEvent e) {&&&&&&& String order=e.getActionCommand();&&&&&&& if(order.equalsIgnoreCase("退出程序"))&& System.exit(0);&&&&&&& if(order.equalsIgnoreCase("增加课程")){&&&& // 课程数目超过默认值,利用ArrayList和GridLayout实现扩容,增加新的组件&&&&&&&&&&& int old_rows=gl.getRows();&&&&&&&&&&& gl.setRows(old_rows+5);&&&&&&&&&&& for(int i=old_rows-1;i&gl.getRows()-1;i++){&&&&&&&&&&&&&&& index_list.add(new JLabel(String.valueOf(i+1)));&&&&&&&&&&&&&&& table.add(index_list.get(i));&&&&&&&&&&&&&&& score_list.add(new JTextField(3));&&&&&&&&&&&&&&& table.add(score_list.get(i));& & & & & & & & credit_list.add(new JTextField(3));&&&&&&&&&&&&&&& table.add(credit_list.get(i));&&&&&&&&&&& }&&&&&&&&&&& f.revalidate();&&&& //& 重新布局,保证正确显示&&&&&&& }&&&&&&& if(order.equalsIgnoreCase("开始计算")){&&&&&&&&&&& int flag=0;&&&&&&&&&&& for(int i=0;i&gl.getRows()-1;i++){& & & & &if(!score_list.get(i).getText().equalsIgnoreCase("")&&!score_list.get(i).getText().equalsIgnoreCase("")){& & & & & & & & & //& 只有学分和成绩都已填写的课程才能进入运算&&&&&&&&&&&&&&&&&&& double score_digit=Double.parseDouble(score_list.get(i).getText());&&&&&&&&&&&&&&&&&&& double credit_digit=Double.parseDouble(credit_list.get(i).getText());&&&&&&&&&&&&&&&&&&& if(score_digit&=0&&score_digit&=100&&credit_digit&=0){&&&&& //& 数据有效性检查&&&&&&&&&&&&&&&&&&&&&&& total_credit=total_credit+credit_&&&&&&&&&&&&&&&&&&&&&&& credit_score=credit_score+credit_digit*score_&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&& else {&&&&&&&&&&&&&&&&&&&&&&& flag=i+1;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&& }&&&&&&&&&&& }&&&&&&&&&&& if(flag!=0)&&&& gpa.setText("第"+flag+"门课程的信息有误,请重新输入");&&&&&&&&&&& else{&&&&&&&&&&&&&&& total_gpa=credit_score/total_&&&&&&&&&&&&&&& gpa.setText("所输入课程的总学分为"+(int)total_credit+",学分绩为"+format_1.format(total_gpa)+"。");&&&&&&&&&&& }&&&&&&& }&&& }}}

我要回帖

更多关于 swing 关闭按钮事件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信