
AWT包含很多类和接口属于GUI编程。元素 窗口按钮文本框。java.awt: ComponentButton,TextArea,Label.Container, Window, Panel,Frame,Dialog,AppletFrame 相当于Delphi中的 Form可以单独存在。 .setVisible(true); .setBounds(x,y,w,h); .setBackground(color); Panel: 不可以单独存在。 .setBounds(x,y,w,h); .setBackground(color); frame.add(panel); //设置容器。一个简单的画矩形和画圆程序import java.awt.*; public class Demo1 { public static void main(String[] args) { new MyPaint().loadFrame(); } } class MyPaint extends Frame { public void loadFrame(){ setBounds(400,200,800,600); setVisible(true); } Override public void paint(Graphics g) { //super.paint(g); //这个应该相当于Delphi中的herited; g.setColor(Color.red); g.drawOval(100,100,100,100); g.fillOval(100,100,100,100); g.setColor(Color.blue); g.fillRect(200,200,400,300); } public MyPaint() { } }3. 布局管理器Layout流式布局。 类似delphi的AlCenter之类的.就是所有控件在容器中的排列对齐模式。常用有FlowLayout.LEFT 和 FlowLayout.CENTER(默认)东西南北中布局。BorderLayout直译是边界布局类似DelphiRX开发界面需要设置5个方向上的控件。程序运行时各个方向上的控件都会自动铺满的效果。在Frame中布局的时候可以直接用 frame.add(childComp,BorderLayout.WEST)来指定布局但是在Panel中布局的时候必须创建的时候new Panel(BorderLayout()); 否则直接指定失效。表格布局。GridLayout( rows,cols); 表格布局中控件排版的顺序是先排满行再往列(下)延伸。如果控件的总数超过表格设置则会自动增加列来排多余的控件但总体顺序还是满行再下延列。下面是一个比较复杂的布局例子这个例子实现了在界面上布局10按钮的模式上部4个下部6个。整个模式为btn1btn5btn2btn6btn3btn7btn8btn4btn9btn10设计思路是先对整体Frame进行表格布局分成上下部分 然后上下部分分别都使用东南西北中布局不过只用西中东其中“中”是panel。最后再在中部panel里再次使用表格布局。核心语句setLayout和add(xxx, BorderLayout.yyy) java import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener;public class HomeWork {public static void main(String[] args) {Frame frm new Frame(家庭作业);Panel pnl1 new Panel(new BorderLayout());Panel pnl2 new Panel(new BorderLayout());Panel pnl3 new Panel();Panel pnl4 new Panel();pnl1.setBackground(Color.blue);pnl2.setBackground(Color.yellow);pnl3.setBackground(Color.lightGray);pnl4.setBackground(Color.pink);//试试表格布局frm.setLayout(new GridLayout(2,1));frm.add(pnl1);frm.add(pnl2);Button btn1 new Button(btn1);Button btn2 new Button(btn2);Button btn3 new Button(btn3);Button btn4 new Button(btn4);Button btn5 new Button(btn5);Button btn6 new Button(btn6);Button btn7 new Button(btn7);Button btn8 new Button(btn8);Button btn9 new Button(btn9);Button btn10 new Button(btn10);//在第一个panel上布局东中西pnl1.add(btn1,BorderLayout.WEST); //边界布局失败pnl1.add(pnl3,BorderLayout.CENTER);pnl1.add(btn2,BorderLayout.EAST);//在第二个panel上布局东中西pnl2.add(btn3,BorderLayout.WEST);pnl2.add(pnl4,BorderLayout.CENTER);pnl2.add(btn4,BorderLayout.EAST);//在第三个panel上进行表格布局pnl3.setLayout(new GridLayout(2,1));pnl3.add(btn5);pnl3.add(btn6);//在第四个panel上布局2x2表格pnl4.setLayout(new GridLayout(2,2));pnl4.add(btn7);pnl4.add(btn8);pnl4.add(btn9);pnl4.add(btn10);frm.setBounds(500,200,800,600);//frm.pack();frm.setVisible(true);frm.addWindowListener(new WindowAdapter() {Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});}}### 4. 监听事件来自java.awt.event 相当于给特定Form增加一个OnClose时间。java窗体点关闭时默认无动作的。 java frame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ //super.windowClosing(e); System.exit(0); //这里在初始化触发器时就重写了事件内容。 } }) //这里才是窗口监听器参数结束。关闭事件可以分开代码写方法windowsClose(frm); ... private static void windowsClose(Frame afrm){ afrm.addWindowListener(new WindowAdapter(){ Override public void windowsClosing(WindowEvent e){ System.exit(0); } }); } //这样写也行跟下面的ActionListener写法还不一样这里没有用到WindowAdapter的变量。监听就相当于Delphi的事件代码从接口接收一个消息。WindowsAdapter 是一个抽象类 继承三个接口:public abstract class WindowAdapter implements WindowListener, WindowStateListener, WindowFocusListener也就是说通常的窗体触发事件来自三个方向窗体消息窗体状态信息窗体焦点信息。按钮的监听button.addActionListener(new ActionListener(){ Override public void actionPerformed(ActionEvent e){ System.out.println(Button Click); } })当然为了层次分明也可以分开写MyActionListener myAct new MyActionListener(); button.addActionListener(myAct); .... class MyActionListener implements ActionListener{ //注意这里是用类来继承一个接口。 Override public void actionPerformed(ActionEvent e) { System.out.println(Button Click); if (e.getActionCommand().equals(AStr){ //这里AStr默认为按钮getCaption. //执行某个按钮别点击的事件;我们可以提前用btn.setActionCommand(AStr);指定按钮信息 } } }以上两种效果是一样的。ActionEvent 和ActionListener都是来自 java.awt.event。ActionEvent是类ActionListener是接口。由于接口需要实例化方法所以直接new的话就必须带方法体。ActionListener继承于另一个接口 java.util.EventListener.目前只具备一个方法 public void actionPerformed(ActionEvent e);5. 了解文本编辑器TextField文本编辑器同按钮一样通过接口ActionListener来实现事件由回车触发。class MyAct implements ActionListener{ Override public void actionPerformed(ActionEvent e){ //这里注意用强行转换操作了e.getSource(),我们可以认为它的意义就是Delphi中的Sender TextField field(TextField)e.getSource(); System.out.println(field.getText()); field.setText(); } }textField.setEchoChar(*); //可以通过这个方法实现掩码输入。textField.setText(Astr); //直接设置文本。构造方法的参数是文本容纳的字符数 new TextField( N );6. 简易计算器的实现以及组合内部类的了解。OOP原则能使用组合就不使用继承。继承语法class A extends B{}组合语法:class A {public B b;//这里所有B类的方法由b带出。}计算器的设计源码这里保留了原本的独立监听事件MyCalculaterListener并改为使用内部类InnerListener。这使得几个TextField参数传输数据更方便。import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestCalc { public static void main(String[] args) { new MyCalculator().loadFrame(); } } class MyCalculator extends Frame { TextField fd1,fd2,fd3; public void loadFrame(){ fd1 new TextField(10); fd2 new TextField(10); fd3 new TextField(10); Button btn1 new Button(); //btn1.addActionListener(new MyCalculaterListener(fd1,fd2,fd3));原有的非常繁琐。 btn1.addActionListener(new InnerListener()); Label lbl1 new Label(); setLayout(new FlowLayout()); add(fd1); add(lbl1); add(fd2); add(btn1); add(fd3); pack(); setVisible(true); } public MyCalculator() { } //用内部类实现监听 private class InnerListener implements ActionListener{ Override public void actionPerformed(ActionEvent e) { int n1 0,n20; try { n1 Integer.parseInt(fd1.getText()); n2 Integer.parseInt(fd2.getText()); }catch (NumberFormatException excp){ System.out.println(非法字符e); }catch (Exception excp){ throw excp; }finally { } fd3.setText( (n1n2)); fd1.setText(); fd2.setText(); } public InnerListener() { super(); //this.mycalcmycalc; } } } class MyCalculaterListener implements ActionListener{ //private TextField fd1,fd2,fd3; MyCalculator mycalc; Override public void actionPerformed(ActionEvent e) { int n1 0,n20; try { n1 Integer.parseInt(mycalc.fd1.getText()); n2 Integer.parseInt(mycalc.fd2.getText()); }catch (NumberFormatException excp){ System.out.println(非法字符e); }catch (Exception excp){ throw excp; }finally { } mycalc.fd3.setText( (n1n2)); mycalc.fd1.setText(); mycalc.fd2.setText(); } //用构造方法传参数 //public MyCalculaterListener(TextField fd1, TextField fd2,TextField fd3) { public MyCalculaterListener(MyCalculator mycalc) { this.mycalcmycalc; //this.fd1mycalc.fd1; this.fd2mycalc.fd2; this.fd3mycalc.fd3; } }从计算器的设计上我们能感悟到的东西对于重要的功能应该独立建立类来处理。2.对于对象的属性我们需要定义在类根下。然后初始化的过程可以单独定义一个方法。3.对于事件的处理我们应该尽量使用内部类 private class来处理这样方便在事件中对对象的各种属性方法进行调用。4.对于方法参数尽量使用引用类型参数可以避免重复开辟空间。5.对于基础数据类型变量系统要求必须初始化才能参与加减乘除。但是try{..}内容中的初始化会被编译器忽略。6.main方法中尽量少写东西只写必要的类和方法调用即可没必要在main方法中初始化一些变量。7. 重视内部类的使用java内部类是定义在java类内部的嵌套类主要分为成员内部类静态嵌套类方法内部类匿名内部类。4种。核心特征包括编译后生成独立的.class文件格式为外部类名 $内部类名。 以及直接访问外部类成员的权限差异无论外部类成员是否private。内部类是为多重继承问题提供补充方案减少代码冗余。由于静态只能位于类的外部一级所以内部类中是不可能拥有静态数据或者静态内部类。成员内部类依附于外部类的实例可访问外部类所有成员。静态嵌套类独立存在仅能访问静态成员。这个属于顶级嵌套类技术与外部类无实例关联。方法内部类受限于局部变量的final修饰和作用域。定义时会出现在一个方法内。只能在该方法内实例化而不可以在此方法外对其实例化。 方法内部类对象不能使用内部类所在方法的非final变量权限很小)。原因方法局部变量是在栈上方法周期结束栈数据删除。但方法结束后方法内部类对象依然可能存在因为生命周期的问题所以内部类对象无法访问外部非final成员。匿名内部类无显示类名常用于接口实现或继承扩展。8 . java.awt包中的控件和常用类Button; Canvas; Checkbox; CheckboxGroup, CheckboxMenuItem, Choice, Color, ColorPaintContext(富文本),Component, Container, Cursor, Desktop, Dialog, Dimension, FileDalog, Font, Frame, Graphics, Image,Label, Menu, MenuBar, MenuItem, Panel, Point, Queue, PopupMenu, Rectangle, Scrollbar, TextArea(Memo),TextField比较新的: FontMetrics 字体信息对象含坡度(ascent/descent)行间距(leading)等信息用于画布绘制文字。另外java.awt.event 包内也包含绝大部分事件定义。 其中Event 和 Adapter结尾的一般是继承接口的抽象方法而Listener结尾的全部都是接口。常用的组件 以及支持的事件 Component Type | Events supported by this component Adjustable AdjustmentEvent Applet ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Button ActionEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Canvas FocusEvent, KeyEvent, MouseEvent, ComponentEvent Checkbox itemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent CheckboxMenultem ActionEvent, ItemEvent Choice ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Component FocusEvent, KeyEvent, MouseEvent, ComponentEvent Container ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Dialog ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent FileDialog ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Frame ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Label FocusEvent, KeyEvent, MouseEvent, ComponentEvent List ActionEvent, FocusEvent, KeyEvent, MouseEvent, ItemEvent, ComponentEvent Menu ActionEvent MenuItem ActionEvent Panel ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent PopupMenu ActionEvent Scrollbar AdjustmentEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ScrollPane ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent TextArea TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent TextComponent TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent TextField ActionEvent, TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent Window ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent了解组件的事件只需要取得对应事件的名字然后把Event改成Listener就可以在内部类里实现对应的 接收器接口。对象只需要使用add前缀接收器就可以来增加对应的事件参数看情况选择Listener系列接口或者对应触发器Adapter这是一个抽象类。在多于1个的事件中选择对应触发器(或者叫适配器)可以简化代码。我们可以了解一下哪些接收器(监听器)包含多个方法。如下表Listener interface/adapter | Methods in interface | ActionListener actionPerformed(ActionEvent) AdjustmentListener adjustmentValueChanged(AdjustmentEvent) ComponentListener componentHidden(ComponentEvent) ComponentAdapter componentShown(ComponentEvent) componetMoved(ComponetEvent) componetResized(ComponentEvent) ContainerListener componentAdded(ContainerEvent) ContainerAdapter componentRemoved(ContainerEvent) FocusListener focusGained(FocusEvent) FocusAdapter focusLost(FocusEvent) KeyListener keyPressed(KeyEvent) KeyAdapter keyRelease(KeyEvent) keyTyped(KeyEvent) MouseListener mouseClicked(MouseEvent) MouseAdapter mouseEnterd(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) MouseMotionListener mouseDragged(MouseEvent) MouseMotionAdapter mouseMoved(MouseEvent) WindowsListener windowOpend(WindowsEvent) WindowsAdapter windowClosing(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) ItemListener itemStateChanged(ItemEvent) TextListener textValueChanged(TextEvent)9. 代码中吸取营养GoodTechniquepackage com.Murphy; /* 这个程序的作用是捕获各个区域的鼠标坐标 */ // GoodTechnique.java // Your first choice when overriding components // should be to install listeners. The code is // much safer, more modular and maintainable. import java.awt.*; import java.awt.event.*; class Display { public static final int //定义消息类型 EVENT 0, COMPONENT 1, MOUSE 2, MOUSE_MOVE 3, FOCUS 4, KEY 5, ACTION 6, LAST 7; public String[] evnt; //事件的本质其实就是一个String这里定义的是事件组,下标对应消息类型存放一组消息。 Display() { evnt new String[LAST]; for(int i 0; i LAST; i) evnt[i] new String(); } //这里是精髓用一个方法输出7行信息对应每一种事件。 public void show(Graphics g) { for(int i 0; i LAST; i) g.drawString(evnt[i], 0, 10 * i 10); //直接用画布输出字串 } } //定义一个可以接收鼠标位置信息的panel类 class EnabledPanel extends Panel { Color c; int id; Display display new Display(); //这里利用Display类在画布中显示事件信息。 public EnabledPanel(int i, Color mc) { //用panel的ID和底色来初始化 id i; c mc; //颜色放入成员变量 setLayout(new BorderLayout()); add(new MyButton(), BorderLayout.SOUTH); addComponentListener(new CL()); addFocusListener(new FL()); addKeyListener(new KL()); addMouseListener(new ML()); addMouseMotionListener(new MML()); } // To eliminate flicker: Override public void update(Graphics g) { //更新画布 paint(g); } Override public void paint(Graphics g) { //画布作图颜色宽高填充区域带事件字符串显示区域 g.setColor(c); Dimension s getSize(); g.fillRect(0, 0, s.width, s.height); g.setColor(Color.black); display.show(g); } // Dont need to enable anything for this: Override public void processEvent(AWTEvent e) { display.evnt[Display.EVENT] e.toString(); repaint(); super.processEvent(e); //保持父类消息事件 } //实现组件监听得到各种事件的消息串 class CL implements ComponentListener { public void componentMoved(ComponentEvent e) { display.evnt[Display.COMPONENT] Component moved; repaint(); } public void componentResized(ComponentEvent e) { display.evnt[Display.COMPONENT] Component resized; repaint(); } public void componentHidden(ComponentEvent e) { display.evnt[Display.COMPONENT] Component hidden; repaint(); } public void componentShown(ComponentEvent e) { display.evnt[Display.COMPONENT] Component shown; repaint(); } } class FL implements FocusListener { public void focusGained(FocusEvent e) { display.evnt[Display.FOCUS] FOCUS gained; repaint(); } public void focusLost(FocusEvent e) { display.evnt[Display.FOCUS] FOCUS lost; repaint(); } } //得到键盘消息键盘的消息值e 其实就是每个按键的ASCII码值的字符表示 class KL implements KeyListener { public void keyPressed(KeyEvent e) { display.evnt[Display.KEY] KEY pressed: ; showCode(e); } public void keyReleased (KeyEvent e){ display.evnt[Display.KEY] KEY released: ; showCode(e); } public void keyTyped (KeyEvent e){ display.evnt[Display.KEY] KEY typed: ; showCode(e); } void showCode (KeyEvent e){ int code e.getKeyCode(); display.evnt[Display.KEY] KeyEvent.getKeyText(code); repaint(); } } class ML implements MouseListener { public void mouseClicked(MouseEvent e) { requestFocus(); // Get FOCUS on click display.evnt[Display.MOUSE] MOUSE clicked; showMouse(e); } public void mousePressed(MouseEvent e) { display.evnt[Display.MOUSE] MOUSE pressed; showMouse(e); } public void mouseReleased(MouseEvent e) { display.evnt[Display.MOUSE] MOUSE released; showMouse(e); } public void mouseEntered(MouseEvent e) { display.evnt[Display.MOUSE] MOUSE entered; showMouse(e); } public void mouseExited(MouseEvent e) { display.evnt[Display.MOUSE] MOUSE exited; showMouse(e); } void showMouse(MouseEvent e) { display.evnt[Display.MOUSE] , x e.getX() , y e.getY(); repaint(); } } class MML implements MouseMotionListener { public void mouseDragged(MouseEvent e) { display.evnt[Display.MOUSE_MOVE] MOUSE dragged; showMouse(e); } public void mouseMoved(MouseEvent e) { display.evnt[Display.MOUSE_MOVE] MOUSE moved; showMouse(e); } //鼠标消息用画布字串输入记录当前的鼠标坐标鼠标消息对应的就是坐标可以用e.getX()和e.getY()得到 void showMouse(MouseEvent e) { display.evnt[Display.MOUSE_MOVE] , x e.getX() , y e.getY(); repaint(); } } } class MyButton extends Button { int clickCounter; String label ; public MyButton() { addActionListener(new AL()); } public void paint(Graphics g) { //绿色按钮南北布局南黑色边框 g.setColor(Color.green); Dimension s getSize(); g.fillRect(0, 0, s.width, s.height); g.setColor(Color.black); g.drawRect(0, 0, s.width - 1, s.height - 1); drawLabel(g); } private void drawLabel(Graphics g) { FontMetrics fm g.getFontMetrics(); int width fm.stringWidth(label); int height fm.getHeight(); int ascent fm.getAscent(); //上坡度基线到字符顶的距离 int leading fm.getLeading(); //行间距 int horizMargin (getSize().width - width) / 2; //水平缩进 按钮宽度减去字符串宽度除以2这样基本居中 int verMargin (getSize().height - height) / 2; g.setColor(Color.red); g.drawString(label, horizMargin, //这个很经典要学会这些参数。 verMargin ascent leading); } class AL implements ActionListener { public void actionPerformed(ActionEvent e) { //这里可以把按钮上的点击次数记录显示出来。 clickCounter; label click # clickCounter e.toString(); repaint(); } } } public class GoodTechnique extends Frame { GoodTechnique() { //用表格模式增加3个记录事件带button的Panel,这样右下角会空出一个区域。 setLayout(new GridLayout(2,2)); add(new EnabledPanel(1, Color.cyan)); add(new EnabledPanel(2, Color.lightGray)); add(new EnabledPanel(3, Color.yellow)); } public static void main(String[] args) { Frame f new GoodTechnique(); f.setTitle(Good Technique); f.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e){ System.out.println(e); System.out.println(Window Closing); System.exit(0); } }); f.setSize(700,700); f.setVisible(true); } }