AWT简介(了解!!)

 

为什么需要GUI

我们前面编写的程序命令行的,用户的体验度极差。

 

抽象窗口工具包(Abstract Window Tookit)是为java程序提供建立图形用户界面(Graphics User Interface GUI)的工具集。主要包含如下组件:

1.      用户界面组件

2.      事件处理模型

3.      图形图像工具(形状、颜色、字体)

4.      布局管理器

 

AWT的优势:

1.      最早的JAVA GUI包,内嵌到JDK中,无需引入其他类,功能稳定

2.      AWT组件都是线程安全

3.      界面编程基础.  学会AWT, 很容易去学swing/SWT等功能较强大的GUI组件.

 

AWT的缺点:

1.      组件的创建完全依赖操作系统实现,导致不同的操作系统下出现不同的外观。

说白了,awt的组件是由操作系统绘制的,我们也说awt组件是重量级的组件

这个工具包提供了一套与本地图形界面进行交互的接口。AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,我们把它称为peers。也就是说,当我们利用 AWT 来构件图形用户界面的时候,我们实际上是在利用操作系统所提供的图形库。由于不同操作系统的图形库所提供的功能是不一样的,在一个平台上存在的功能在另外一个平台上则可能不存在。为了实现Java语言所宣称的"一次编译,到处运行"的概念,AWT 不得不通过牺牲功能来实现其平台无关性,也就是说,AWT 所提供的图形功能是各种通用型操作系统所提供的图形功能的交集。由于AWT 是依靠本地方法来实现其功能的,我们通常把AWT控件称为重量级控件。

 

AWT并没有为GUI组件提供真正的实现,而是调用运行平台的GUI组件来创建和平台一致的对等体peers,因此程序中Textarea实际上是windows的多行文本域组件的对等体,具有和他相同的行为。所以,你右键单击textarea会出现菜单…

 

2.      线程安全导致运行速度慢

3.      为了保证程序的可移植性,AWT[雨林木风1] 组件集遵循最大公约数原则,即AWT只拥有所有平台上都存在的组件的公有集合。有些常用的组件不支持,比如:表、树、进度条等。字体也只能支持4种。

 

为什么还需要学习AWT?

实际开发中使用AWT的情况非常少,但是我们仍然有必要学习AWT。主要原因如下:

1.      Swing是在AWT基础上构建的,事件模型和一些支持类(形状、颜色、字体)都一样。掌握AWT有利于后面学习SWING.  Eclipse不是swing开发的,是swt开发的。

2.      学习一下GUI编程。事实上,编程思路和其他语言类似

 

题外话:

SWT的崛起:

SWT本身仅仅是Eclipse组织为了开发 Eclipse IDE环境所编写的一组底层图形界面 API。或许是无心插柳,或是有意为之, 至今为止,SWT无论是在性能和外观上,都超越了SUN公司提供的AWT和SWING。目前Eclipse IDE已经开发到了3.3版本,SWT已经十分稳定。这里指的稳定应该包含两层意思(eclipse的中文意思是日食,遮住太阳的意思) 一是指性能上的稳定,其中的关键是源于SWT的设计理念。SWT最大化了操作系统的图形构件API,就是说只要操作系统提供了相应图形的构件,那么SWT只是简单应用JNI技术调用它们,只 有那些操作系统中不提供的构件,SWT才自己去做一个模拟的实现。可以看出SWT的性能上的稳定大多时候取决于相应操作系统图形构件的稳定性。

 

 

AWT整体关系

 

 

组件和容器

Component是一个具有图形表示能力的对象,可在屏幕上显示,并可与用户进行交互,是没有菜单的 AWT 组件的抽象父类。封装了如下方法:

getComponentAt(int x, int y)
getFont()
getForeground()
getName()
getSize()
paint(Graphicsg)
repaint()
update()
setVisible(booleanb) [微软用户2] 
setSize(Dimension d)
setName(String name)
setBounds(int x,int y, int widhth, int height) 同时设置组件的位置和大小

 

容器Container是Component的子类,容器对象本身也是组件,是可以装其他组件[雨林木风3] 的组件。

AWT中有如下三种容器类型:

Panel:就是一个矩形空间,目的就是为其他组件提供空间管理。特点:不能独立存在,必须被添加到其他容器中;布局管理器默认是FlowLayout。

Window:可独立存在的顶级窗口. 他有两个子类:

Frame:常见的窗口。初始化不可见,需要用setVisible(true)设置为可见。默认是BorderLayout布局管理器

              Dialog:创建对话框。

ScollPanel:增加滚动条用。

 

简单示例:

    public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setBounds(200, 200, 300, 300);

       Button b1 = new Button("aaa");

       TextField field = new TextField();

       frame.add(field);

       frame.add(b1);

//     frame.setLayout(new FlowLayout());

//frame.pack();

       frame.setVisible(true);

    }

后面增加的组建把前面的覆盖了, 原因是是布局管理器的问题,它默认是BorderLayout。改为FlowLayout就可以了。

//增加Panel容器

public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setBounds(200, 200, 300, 300);

      

       Panel panel = new Panel();

       frame.add(panel);

      

       Button b1 = new Button("aaa");

       TextField field = new TextField();

       panel.add(field);

       panel.add(b1);

      

       frame.setLayout(new FlowLayout());

       frame.pack();[雨林木风4] 

       frame.setVisible(true);

    }

 

 

 

 

 

 

 

 

 

布局管理器

为什么需要布局管理器?

为了使生成的GUI具有良好的平台无关性,awt中提供了布局管理器来管理容器中组件的布局,而不是直接设置组件位置和大小。比如:一个按钮,在windows系统下高10px,宽20px,在linux下可能需要15px,宽25px。这样直接设置的话,就需要这样做大量的调整工作。

对于一个组件来说,一般都有一个最佳大小(既没有多余空间,也没有内容被遮挡)[雨林木风5] ,这个最佳大小一般随平台的不同而不同。如果让程序员手动控制调整这个最佳大小的话,不现实。我们可以使用布局管理器来讲组件的大小调整到最佳大小。程序员要做的只是选择合适的布局管理器即可。

常见的布局管理器:

布局管理器

特点

典型代码

效果

FlowLayout

1.       从左到右排列容器中的组件,满了后就折到下一行。(跟我们书写习惯差不多)

    public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setBounds(200, 200, 300, 300);

       for (int i = 0; i < 10; i++) {

           Button b1 = new Button("按钮"+i);

           frame.add(b1);

       }

       frame.setLayout(new FlowLayout());[雨林木风6] 

       frame.setVisible(true);

    }

BorderLayout

1.       将容器区域分为东南西北中五个区域:

2.       添加组件时需要指定到哪个子区域,默认是Center

3.       覆盖问题:如果同一个区域添加多个组件,后面的会覆盖前面的

4.       我们可以通过放置5个子容器,子容器中在放置其他组件。这样就可以放置远远超过5个的组建喽!

public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setLayout(new BorderLayout());

       frame.setBounds(200, 200, 300, 300);

       Button b1 = new Button("按钮"+0);

       Button b2 = new Button("按钮"+1);

       Button b3 = new Button("按钮"+2);

       Button b4 = new Button("按钮"+3);

       Button b5 = new Button("按钮"+4);

       Button b55 = new Button("按钮"+44);

       frame.add(b1, BorderLayout.SOUTH);

        frame.add(b2,BorderLayout.NORTH);

        frame.add(b3,BorderLayout.CENTER);

        frame.add(b4,BorderLayout.WEST);

        frame.add(b5,BorderLayout.EAST);

        frame.add(b55,BorderLayout.EAST);

      

       frame.setVisible(true);

    }

CardLayout

1.       将容器中所有的组件看做一叠卡片,每次只有最上面的卡片才可见。

2.       几个常用方法:

first, last, previous, next, show

3.        

    public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setBounds(200, 200, 300, 300);

       CardLayout layout = new CardLayout();

       Panel panel = new Panel();

       panel.setLayout(layout);

      

       Button b1 = new Button("按钮"+1);

       Button b2 = new Button("按钮"+2);

       Button b3 = new Button("按钮"+3);

      

       panel.add("a",b1);  //不加的话,会抛出异常: java.lang.IllegalArgumentException: cannot add to layout: constraint must be a string

       panel.add("b",b2);

       panel.add("c",b3);

       frame.add(panel);

      

//     layout.first(panel);

       layout.last(panel);

      

       frame.setVisible(true);

    }

 

GridLayout

1.       将容器按照指定行列进行分割,每个网络格大小相同。

2.       默认从左到右,从上到下添加组件

3.       当自定义的行数和列数不满足要求,系统会通过计算重新布置网格。如左边例子,当为3*3放10个组件时,会自动变成如下:

4.        

    public static void main(String[] args) {

       Frame frame = new Frame("Hello AWT!");

       frame.setBounds(200, 200, 300, 300);

       GridLayout layout = new GridLayout(4,3);

       frame.setLayout(layout);

       for (int i = 0; i < 10; i++) {

           Button button = new Button(i+"");

           frame.add(button);

       }

      

       frame.setVisible(true);

    }

 

GridBagLayout

功能强大,使用复杂。与GirdLayout不同,GridBagLayout中的组件可以跨越多个网格,并可以设置网格大小互不相同,从而实现更加灵活的窗口效果。

知道有这个东东,就行了。用到的机会很渺茫。而且,swing中有个BoxLayout完全可以代替他,并且用法简单

 

 

 

 

做一个如下计算器:

分析:

菜单区可先去掉。

字体格式等其他格式都先不管,只要布局对就可以了。

三个区域:

1.       显示区

2.       操作区

3.       数字区

 

 

    public static void main(String[] args) {

       Frame frame = new Frame("简单的计算器");

       frame.setLocation(100, 100);

       Panel p1 = new Panel();

       Panel p2 = new Panel();

       Panel p3 = new Panel();

      

       GridLayout gridLayout = new GridLayout(1,3,2,2);

       GridLayout gridLayout2 = new GridLayout(4,6,2,2);

       TextField tf = new TextField(30);

       p1.add(tf);

      

       Button b1 = new Button("Backspace");

       Button b2 = new Button("CE");

       Button b3 = new Button("C");

       b1.setForeground(Color.red);

       b1.setBackground(Color.blue);

       p2.add(b1);

       p2.add(b2);

       p2.add(b3);

       p2.setLayout(gridLayout);

      

       for(int i=1;i<=24;i++){

           Button btn1 = new Button(i+"");   //如果有耐心,可以讲那些按钮上的字符手动敲进去

           p3.add(btn1);

       }

       p3.setLayout(gridLayout2);

 

       frame.add(p1,BorderLayout.NORTH);

       frame.add(p2,BorderLayout.CENTER);

       frame.add(p3,BorderLayout.SOUTH);

       frame.pack();

       frame.setVisible(true);

frame.setResizable(false);

    }

注:大部分的GUI不能依靠一种布局管理器搞定,而是多个结合使用。

 

 

AWT事件处理模型

 

问题:前面我们的按钮对象,点击以后也不会发生什么事情。就像我们遇到火灾没反应一样。我是监工,你是劳动人民,监视你们劳动,如果不劳动,就抽你。

1.      单位赋予我职责:监工。(监视劳动者是否打盹儿)

2.      劳动者打了个盹

3.      这个盹儿,被监工看到了

4.      监工走上前去抽你

 

整个过程,我们可以细分一下,有几个对象:

劳动者:事件源(Event Source) à可以发生打盹儿,劳动,吃饭这些事件。

打个盹儿:事件(Event)

监工:事件监听器(Event Listener) 和事件处理器(Event handler)

 

当然,恋爱中,这里的监工可以变成你老婆,劳动者可以变成你。事件可以变成看美女。工作,监工就是老板,劳动者就是你;学习中,监工就是老师,你就是劳动者。总之,这个模式符合所以的事情发生和处理过程。所以,这个过程我们是可以抽象的:

1.      注册监听器到事件源

2.      事件源上发生事件(专业点:外部动作触发事件源上的事件)

3.      将事件传递给监听器(专业点:先生成事件对象,然后将对象作为参数传递给事件监听器)

4.      监听器调用相应的方法进行事件处理

 

 

我们点击按钮对象,然后进行相应的处理。也符合上面的模式。咱们写一个最简单的事件处理程序:

public class Test {

    public static void main(String[] args) {

       Frame frame = new Frame("测试事件");

       frame.setBounds(100, 100, 200, 200);

 

       Button btn  = new Button("点我吧");

       btn.addActionListener(new TestListener());

      

       frame.add(btn);

       frame.setVisible(true);

    }

}

 

class TestListener implements ActionListener {

 

    public void actionPerformed(ActionEvent e) {

       // TODO Auto-generated method stub

       System.out.println("谁点我!!");

    }

   

}

AWT中事件处理代码编写过程:

1.  实现相应的Listener接口,定义一个监听类。并通过重写actionPerformed方法来实现对相应事件的处理。

2.  在事件源对象上通过add***Listener方法将1中定义的监听类的对象传递进来。

 

 

处理过程:

1.  注册TestListener到btn

2.  点击btn,触发事件,系统自动生成Event对象

3.  Btn对象将Event对象传递给TestListener对象

4.  TestListener对象调用他的actionPerformed方法进行相应的处理

 

 

简化理解上面过程:

1.  注册事件

2.  发生事件:事件源组件发生事件

3.  处理事件:系统自动调用注册到该事件源组件的监听器相应的方法进行对应处理

 

 

事件源:就是我们学过的Compotent组件

事件:Event,它是由外部事件触发,由系统自动生成的。常见的有如下事件:

低级事件

基于具体的动作的事件。比如:窗口最小化、关闭、失去焦点;键盘按下、松开、单击;鼠标进入、点击、拖放等等。

ComponentEvent:

ContainerEvent:

WindowEvent:

FocusEvent:

KeyEvent:

MouseEvent:

高级事件

不和特定动作关联,而和发生事件的对象关联。比如:

ActionEvent:当按钮、菜单项被单击,TextField中按回车。

ItemEvent:当用户选中或取消某项

TextEvent:当文本框、文本域里面的文本发生改变时触发

AdjustmentEvent:调节事件,当滑动条上调节滑块时触发

事件和事件监听器接口关系总结:

 

 

一个组件可以添加多个监听器。 你女朋友不光监视你是不是看别的美女,也监视你钱怎么花对不对?你可以接收你女朋友的监视,现在也接受老师我的监视。

Event常用的方法测试:

public class Test {

    static Button b2 = new Button("按钮二");

    public static void main(String[] args) {

       Frame frame = new Frame("测试事件");

       frame.setLayout(new FlowLayout());

       frame.setBounds(100, 100, 200, 200);

 

       Button btn  = new Button("点我吧");

       btn.addActionListener(new TestListener());

      

       frame.add(b2);

       frame.add(btn);

       frame.setVisible(true);

    }

}

 

class TestListener implements ActionListener {

 

    public void actionPerformed(ActionEvent e) {

       // TODO Auto-generated method stub

       System.out.println(e.getActionCommand());  //就是“点我吧”

       System.out.println(e.getSource());  //返回事件源对象

       System.out.println(e.getWhen());  //返回事件发生的时间

       System.out.println("谁点我!!");

    }

   

}

 

 

测试上面所有的事件:

WindowEvent事件

public class Test {

    public static void main(String[] args) {

       Frame frame = new Frame("测试事件");

       frame.setLayout(new FlowLayout());

       frame.setBounds(100, 100, 200, 200);

 

       Button btn  = new Button("点我吧");

       TextField field = new TextField(20);

      

       frame.add(btn);

       frame.add(field);

      

       frame.setVisible(true);

       frame.addWindowListener(new TestListener());

    }

}

 

class TestListener implements WindowListener{

 

    public void windowActivated(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口被激活!");

    }

 

    public void windowClosed(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口被关闭");

    }

 

    public void windowClosing(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("用户正在关闭! ");

       System.exit(0);

      

    }

 

    public void windowDeactivated(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口失去焦点");

      

      

    }

 

    public void windowDeiconified(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口被恢复");

    }

 

    public void windowIconified(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口被最小化");

    }

 

    public void windowOpened(WindowEvent e) {

       // TODO Auto-generated method stub

       System.out.println("窗口初次被打开");

    }

}

 

KeyEvent

按下、松开、单击

public class TestEvent {

    public static void main(String[] args) {

       Frame f = new Frame();

       f.setBounds(300, 300, 200, 200);

       Button button = new Button("测试");

       f.add(button);

 

       f.setVisible(true);

 

/* 

 * 一个Component要能够响应键盘事件,必须是可以获得焦点的。 

    而要能够获得焦点,需要满足三个要求,根据Sun的Java   Tuturial,是visible,   enabled,   and   focusable。

    而Frame不满足此要求,所以不能响应键盘事件.  其他的很多组件都是可获得焦点的,比如:Button等。

*/

 

       f.setVisible(true);

       f.setFocusable(true);

       f.setEnabled(true);

       f.addKeyListener(new MyKeyListener());

 

    }

}

 

class MyKeyListener implements KeyListener {

 

    public void keyPressed(KeyEvent e) {

       // TODO Auto-generated method stub

       System.out.println("按下:"+e.getKeyChar());  //返回字符,比如:'a', 按下shift+a返回"A"

       System.out.println(e.getKeyCode());   //返回该键对应的数值

       if(e.getKeyCode()==KeyEvent.VK_0){

           System.exit(0);

       }

       if(e.isShiftDown()&&(e.getKeyCode()==KeyEvent.VK_1)){

           System.out.println("按下shift和1");

       }

[雨林木风7]   }

 

    public void keyReleased(KeyEvent e) {

       // TODO Auto-generated method stub

      

    }

 

    public void keyTyped(KeyEvent e) {

       // TODO Auto-generated method stub

      

    }

   

}

MouseEvent

mouseClicked:单击组件

mouseEntered:鼠标进入组件

mouseExited:鼠标离开组件

mouseReleased:在组件上松开鼠标

mousePressed:在组件上按下鼠标

MouseListener:

单击、进入、离开、按下、松开。

MouseMotionListener:

拖拽、移动

MouseInputListener:[雨林木风8] 

包含上面两种监听器的所以动作

 

MouseListener响应mouse点击的  
  MouseMotionListener响应mouse移动,拖拽等等

public class TestEvent extends Frame {

   

    public static void main(String[] args) {

       TestEvent f = new TestEvent();

       f.setLayout(new FlowLayout());

       f.setBounds(300, 300, 200, 200);

      

       f.setVisible(true);

       f.addMouseListener(new MyMouseListener2());

       f.addMouseMotionListener(new MyMouseListener3());

    }

}

 

class MyMouseListener3 implements MouseMotionListener{

 

    public void mouseDragged(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("坐标:("+e.getX()+","+e.getY()+")");

      

    }

 

    public void mouseMoved(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("移动:("+e.getX()+","+e.getY()+")");

    }

   

}

 

class MyMouseListener2 implements MouseListener {

 

    public void mouseClicked(MouseEvent e) {

       // TODO Auto-generated method stub

       Point p = e.getPoint();

       System.out.println(p.getX()+"--"+p.getY());  //返回点击时的坐标

       System.out.println("单击");

    }

 

    public void mouseEntered(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("进入");

    }

 

    public void mouseExited(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("离开");

    }

 

    public void mousePressed(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("按下");

    }

 

    public void mouseReleased(MouseEvent e) {

       // TODO Auto-generated method stub

       System.out.println("松开");

    }

}

 

 

 

事件适配器

问题:上面写关于Window的事件处理,我们并不是每次都需要对所有事件进行处理,很可能只需要处理某个事件,比如:Close。

适配器只是监听器接口的空实现;可以看看源代码。如果某个监听器只有一个方法,就没有必要在定义相应的适配器了。

 

public class Test {

    public static void main(String[] args) {

       Frame frame = new Frame("测试事件");

       frame.setLayout(new FlowLayout());

       frame.setBounds(100, 100, 200, 200);

 

       Button btn  = new Button("点我吧");

       TextField field = new TextField(20);

      

       frame.add(btn);

       frame.add(field);

      

       frame.setVisible(true);

       frame.addWindowListener(new TestAdapter());

    }

}

 

 

class TestAdapter extends WindowAdapter{

 

    @Override

    public void windowClosing(WindowEvent e) {

       // TODO Auto-generated method stub

       System.exit(0);

    }

}

 

 

 

事件监听器常见的定义形式:

1.      内部类定义(前面的都是这种形式!)

2.      匿名内部类(很多时候,事件处理没有复用价值[雨林木风9] ,只是临时使用一次,所以使用匿名内部类更是一种常用的方法!)

       frame.addWindowListener(new WindowAdapter(){

           public void windowClosing(WindowEvent e) {

              // TODO Auto-generated method stub

              System.exit(0);

           }

       });

 

 

AWT其他组件:

按钮、文本域、文本框、标签、画布等等。

 

AWT的菜单:

特点:

1.       所有菜单类继承的是MenuComponent,而不是Component。

2.       MenuComponent操作比较单调。只能添加到Frame对象中,只能出现在Frame的顶部,不能使用布局管理器管理。

有三个相关类:

1.       MenuBar:是菜单的根基,只能添加到Frame对象中。

2.       Menu:菜单,可以添加到MenuBar或其他MenuBar中。

3.       MenuItem:菜单项,菜单中的“叶子节点”。通常被添加到Menu中,可以增加ActionListener实现相应的操作处理。

4.       CheckboxMenuItem:可复选的菜单项

 

简单示例:

模拟画图软件的菜单:

    public static void main(String[] args) {

       Frame frame = new Frame("测试事件");

       frame.setLayout(new FlowLayout());

       frame.setBounds(100, 100, 200, 200);

 

       MenuBar bar = new MenuBar();

       frame.setMenuBar(bar);

      

       Menu menu1 = new Menu("文件");

       Menu menu2 = new Menu("编辑");

       Menu menu3 = new Menu("查看");

       Menu menu4 = new Menu("图像");

       bar.add(menu1);

       bar.add(menu2);

       bar.add(menu3);

       bar.add(menu4);

      

       CheckboxMenuItem cmi1 = new CheckboxMenuItem("工具箱");

       CheckboxMenuItem cmi2 = new CheckboxMenuItem("颜料盒");

       cmi1.addItemListener(new ItemListener(){

           public void itemStateChanged(ItemEvent e) {  //选中和取消选中都会触发

              // TODO Auto-generated method stub

              System.out.println("haha");

           }

       });

      

//     MenuItem item1 = new MenuItem("查看位图");

      

       //创建菜单项的快捷方式

       MenuShortcut cut1 = new MenuShortcut(KeyEvent.VK_B); //按下:ctr+b,及相当于点击指定菜单项

       MenuItem item1 = new MenuItem("查看位图",cut1);

      

      

       item1.addActionListener(new ActionListener(){

           public void actionPerformed(ActionEvent e) {

              // TODO Auto-generated method stub

              System.out.println("刚刚点击了查看位图!");

           }

          

       });

      

       //Menu对象中套Menu对象,可以实现多级菜单!

       Menu sub1 = new Menu("缩放");

       MenuItem subItem1 = new MenuItem("大尺寸");

       subItem1.setEnabled(false);   //可以变为灰色,不能点击!

       MenuItem subItem2 = new MenuItem("自定义");

       sub1.add(subItem1);

       sub1.add(subItem2);

      

       menu3.add(cmi1);

       menu3.add(cmi2);

       menu3.addSeparator();   //这个位置生成分割线

       menu3.add(item1);

       menu3.add(sub1);

      

      

      

       frame.setVisible(true);

    }

 

有兴趣的同学,可以完善。不过,没什么必要了。

 


 [雨林木风1]事实上,它是Sun不推荐使用的,只是为了确保向下兼容和支持Swing。

 [微软用户2]组件的默认的Visible属性是FALSE。

 [雨林木风3]容器中可以装普通组件,也快成装容器

 [雨林木风4]Awt编程经常用pack来讲窗口调整到合适大小。而不是直接指定大小

 [雨林木风5]调整到既能全部显示自己的信息,又不影响旁边其他的组建。

 [雨林木风6]Frame默认的布局管理器是BorderLayout

 [雨林木风7]复合键的处理

 [雨林木风8]对应swing组件的:addMouseInutListener

 [雨林木风9] 如果有需要复用的代码,通常封装成方法。