java GUI 1:事件处理及图形操作

本文介绍了 AWT 图形用户界面编程的基础知识,包括 GUI 组件分类、AWT 线程管理、事件处理机制及图形操作等内容。通过具体编程示例展示了如何使用 Java 实现 GUI 应用。

AWT的基本知识

GUI全称是Graphical User Interface,即图形用户界面,JDK中提供了AWTSwing两个包,用于GUI程序的设计和开发,后者为前者的丰富与扩充。

GUI组件可以分为两大类:基本组件和容器,分别是java.awt.Component

java.awt.Container的直接或间接子类,由于Container也是组件,所以它也是Component的子类。

程序的GUI部分的线程管理。如果程序中有GUI的部分,就会创建一个新的AWT线程,该线程负责管理程序的GUI部分。

编程举例:让框架窗口显示5秒后关闭,查AWT的线程的状态。

import java.awt.*;

public class TestFrame {

       public static void main(String[] args) {

              Frame f=new Frame("Hello");//创建一个标题为Hello的窗体

              f.add(new Button("OK"));//加入按钮,标签为OK

              f.setSize(300,300);//设置大小

              f.setVisible(true);

              try

              {

                     Thread.sleep(5000);

              }

              catch(Exception e)

              {

                     e.printStackTrace();

              }

              f.dispose();//将窗口释放

              //当所有的GUI组件被释放后,AWT线程也就结束了

   }

}

AWT事件处理

 

事件处理机制

三个重要概念:

事件:用户对组件的一个操作,称之为一个事件。事件源:发生事件的组件就是事件源。事件处理器:某个java类中的负责处理事件的成员方法

事件的分类

按对组件的物理操作(如按键、点击鼠标等)及组件的反应将事件分类,每一类事件都有一个对应的java,如:MouseEventWindowEventActionEvent…

按事件的性质分类:低级事件与语义事件(高级事件)

编程举例:实现关闭窗口的事件处理,用不同层次的事件类型来表示同一个事件源对象。

import java.awt.event.*;

import java.awt.Window;

 

public class MyWindowListener  implements WindowListener{

//事件监听器类

       public void windowOpened(WindowEvent e) {}

 

       public void windowClosing(WindowEvent e) {

    //处理正准备关闭窗口时发生的事件

        e.getWindow().setVisible(false);

        ((Window)e.getComponent()).dispose();

        //dispose()为窗口专用的方法

        /*e.getSource()e.getWindow()e.getComponent()效果类似,

         *只是要注意返回值*/

         System.exit(0);

       }

 

       public void windowClosed(WindowEvent e) {}

    //处理已关闭窗口后发生的事件

       public void windowIconified(WindowEvent e) {}

 

       public void windowDeiconified(WindowEvent e) {}

 

       public void windowActivated(WindowEvent e) {}

 

       public void windowDeactivated(WindowEvent e) {}

}

 

import java.awt.*;

public class TestFrame {

       public static void main(String[] args) {

              Frame f=new Frame("Hello");

              f.add(new Button("OK"));

              f.setSize(300,300);

              f.setVisible(true);

              f.addWindowListener(new MyWindowListener());//注册监听器

   }

}

由上可得,处理发生在某个GUI组件上的XxxEvent事件,其处理的通用流程为:

a、  编写一个实现了XxxListener接口的事件监听类;

b、  XxxListener类中的用于处理该事件情况的方法中,编写处理代码;

c、  调用组件的addXxxListener方法,将XxxListener创建的实例对象注册到GUI组件

 

为了简化事件监听器的编写,java中提供了大多数事件监听器接口的最简单的实现类,称之为事件适配器类,当需要处理事件时,只需继承相应的适配器类,并覆盖对应的方法即可:

import java.awt.event.WindowAdapter;

import java.awt.Window;

import java.awt.event.WindowEvent;

 

public class TestWindowAdapter extends WindowAdapter {

       public void windowClosing(WindowEvent e) {

        e.getWindow().setVisible(false);

        ((Window)e.getComponent()).dispose();

        System.exit(0);

       }

}

 

 

还有更简单的匿名类,用于事件的处理:(注意以下代码应在一个方法中)

addWindowListener(new WindowAdapter(){

               public void windowClosing(WindowEvent e)

               {

                      dispose();

                   System.exit(0);

               }

        });

 

事件处理的多重运用:

一个组件上的一个动作可以产生多种不同类型的事件

一个事件监听器对象可以注册多个事件源上

在一个事件源上也可以注册对同一类事件进行处理的多个事件监听器

 

修改组建的默认事件处理方式

只有在一个组件上注册了某事件的事件监听器对象后,组件才会产生相应的事件对象,当一个组件发生某事件后,系统就调用processEvent方法,而该方法会根据发生的事件类型,调用相应的processXxxEvent方法。processXxxEvent方法就会调用事件监听器中的方法,并把事件对象传递给那个方法。

我们要修改某组件的事件的处理方式,可以通过修改组件的processEvent方法,或修改processXxxEvent方法来实现。当我们想在一个方法中修改所有的事件处理方式时,就选择修改processEvent方法,否则最好选择修改改processXxxEvent方法就可以了。若要修改某组件的事件处理方式,就要创建继承它的子类,在子类中才能修改processXxxEvent方法。

程序调用组件的enableEvents(long eventsToEnable)方法时,可以在即使没有注册监听器的情况下,组件也能够对参数所表示的类型的事件进行响应和产生相应的事件处理对象。该方法的参数表示了一种或几种类型的事件,它的每一个比特位代表一类事件,比特位为1表示包含相应的事件,为0则表示不包含,为了方便使用,java提供了静态常量来代表相应的事件。

编程举例:在一个窗口上显示一个按钮,一旦鼠标移动到这个按钮上时,按钮就移动到了其他位置,这样,鼠标就永远无法点击到这个按钮。

import java.awt.*;

import java.awt.event.*;

public class MyButton extends Button{

       private MyButton friend=null;

       public MyButton(String title)

       {

              super(title);

              this.enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);

              //仅仅启动鼠标移动事件,屏蔽了其他事件

       }

       public void setFriend(MyButton friend)

       {

              this.friend=friend;

       }

       protected void processMouseMotionEvent(MouseEvent e)

//修改processXxxEvent方法

       {

              setVisible(false);

              friend.setVisible(true);

       }

}

 

 

import java.awt.event.*;

import java.awt.*;

public class TestMyButton extends Frame{

 

    public TestMyButton()

    {

        addWindowListener(new WindowAdapter(){

               public void windowClosing(WindowEvent e)

               {

                      dispose();

                   System.exit(0);

               }

        });

    }

 

    public static void main(String[] args) {

        TestMyButton mainFrame=new TestMyButton();

        MyButton btn1=new MyButton("catch me");

        MyButton btn2=new MyButton("catch me");

        btn1.setFriend(btn2);

        btn2.setFriend(btn1);

        mainFrame.setSize(400,400);

        mainFrame.setTitle("Hello");

        mainFrame.add(btn1,"North");

        mainFrame.add(btn2,"South");

        mainFrame.setVisible(true);

        btn2.setVisible(false);

        //在主界面没有设置显示之前,上面的组件不要调用setVisible方法

    }

}

 

GUI组件上的图形操作

Graphics类与图形绘制

Component.getGraphics方法获取Graphics

变成举例:以鼠标在窗口中按下时的位置作起始点,鼠标释放时的位置作为终止点,在鼠标释放时将直接画出,并在每条直线的起始和终止点位置上打印出它们的坐标值。
import java.awt.*;

import java.awt.event.*;

public class DrawLine extends Frame{

 

       public DrawLine()

       {

              addMouseListener(new MouseAdapter(){

                     int X,Y;

                     public void mousePressed(MouseEvent e)

                     {

                            X=e.getX();Y=e.getY();

                     }

                     public void mouseReleased(MouseEvent e)

                     {

                            Graphics g=getGraphics();

                            g.drawString("始:"+X+","+Y,X,Y);

                            g.drawString("终:"+e.getX()+","+e.getY(),e.getX(),e.getY());

      // drawString方法后两个参数表示的是所绘的矩形区域的左下角的坐标。

                            g.drawLine(X,Y,e.getX(),e.getY());

                     }

              });

              addWindowListener(new WindowAdapter(){

               public void windowClosing(WindowEvent e)

               {

                      dispose();

                   System.exit(0);

               }

        });

       }

 

    public static void main(String[] args) {

           DrawLine drawFrame=new DrawLine();

           drawFrame.setTitle("Hello");

           drawFrame.setSize(400,400);

           drawFrame.setVisible(true);

    }

}

 

组件的重绘处理

每当窗体被恢复或改变大小时,系统就会重画这个窗体及其组件,但不会改变上面由Graphics绘制的图形,甚至在窗体被恢复时,上面原来的由Graphics绘制的图形就消失了。但每当组件被恢复或改变大小时,AWT线程就会调用该组件的paint(Graphics g)方法。所以我们可以在paint方法中编写代码,使得由Graphics绘制的图形会随着窗体的改变(恢复)而改变(恢复)。

import java.awt.*;

import java.awt.event.*;

import java.util.*;

public class DrawLine extends Frame{

    int X,Y;

    int endX,endY;

    Vector vLines=new Vector();

       public DrawLine()

       {

              addMouseListener(new MouseAdapter(){

                     public void mousePressed(MouseEvent e)

                     {

                            X=e.getX();Y=e.getY();

                     }

                     public void mouseReleased(MouseEvent e)

                     {

                            endX=e.getX();endY=e.getY();

                            Graphics g=getGraphics();

                            g.drawString("始:"+X+","+Y,X,Y);

                            g.drawString("终:"+endX+","+endY,endX,endY);

                            g.drawLine(X,Y,e.getX(),e.getY());

                            vLines.add(new MyLine(X,Y,endX,endY));

                     }

              });

              addWindowListener(new WindowAdapter(){

               public void windowClosing(WindowEvent e)

               {

                      dispose();

                   System.exit(0);

               }

        });

       }

    public void paint(Graphics g)

    {

           Enumeration e=vLines.elements();

           while(e.hasMoreElements())

           {

                  MyLine line=(MyLine)e.nextElement();

                  line.drawMe(g);

           }

 

    }

    public static void main(String[] args) {

           DrawLine drawFrame=new DrawLine();

           drawFrame.setTitle("Hello");

           drawFrame.setSize(400,400);

           drawFrame.setVisible(true);

    }

}

 

import java.awt.Graphics;

 

public class MyLine {

       private int X,Y;

       private int endX,endY;

 

       public MyLine(int X,int Y,int endX,int endY)

       {

              this.X=X; this.Y=Y;

              this.endX=endX;

              this.endY=endY;

       }

       public void drawMe(Graphics g)

       {

              g.drawString("始:"+X+","+Y,X,Y);

              g.drawString("终:"+endX+","+endY,endX,endY);

              g.drawLine(X,Y,endX,endY);

       }

}

应用程序不应直接调用paint方法,而是调用repaint()方法,该方法会先调用update()方法,清除组件的表面内容,然后调用paint方法,

可将上程序的public void mouseReleased(MouseEvent e)方法修改为:

       public void mouseReleased(MouseEvent e)

                     {

                            endX=e.getX();endY=e.getY();

                            vLines.add(new MyLine(X,Y,endX,endY));

                            repaint();

                     }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值