GUI编程
Swing和AWT 是java开发GUI常用的技术 . 但是因为外观不太漂亮, 组件数量少, 运行需要JRE环境
(总是几百MJRE包… ), 所以不流行. 但是 ,建议学仍然需要简单的学习和理解.
-
组件( JTable,JList等等)很多都是MVC的经典示范. 学习也可以理解mvc架构的
-
工作时,N年前也可能需要维护awt/swing写的软件 ,尽管可能性很小
-
你可以写一些你自己使用的软件. 还是挺方便的.
艺多不压身
学习了swing还需要学习awt吗?
swing是建立在awt基础上的。 还是要学习的。.原因如下:
-
知识的相关性 . 比如 布局 , 颜色, 字体,事件机制 等 这些都是awt里的内容. 但在swing也经常用在里面.
-
学习成本低, 因为awt和swing编码差别不大, 写法基本一致, 组件的使用也差不多(只需要记住几个不同的地方)
-
不同的使用场景. awt资源消耗少, 运行速度快. 适用于嵌入式等. swing跨平台,组件丰富.
虽然现在用Java做cs很少有人学习,但对我们来说Java基本上,我认为这仍然是一个很好的资源,我们可以 用它来贯穿以前的所有知识,做一些小应用,游戏,等等。你可以把你的一些小想法做成 分享工具!
AWT
一、AWT介绍
-
AWT(Abstract Window Toolkit)包括了很多类和接口,用于Java Application的GUI(Graphics User Interface 编程图形用户界面)。
-
GUI各种元素(如窗口、按钮、文本框等。Java类来实现。
-
使用AWT涉及的类别一般在Java.AWT包括它的子包。
-
Container和Component是AWT两个核心类别。
所有可以显示的图形元素都称为Component,Component它代表了所有可见的图形元素, Component有一种特殊的图形元素叫做Container,Container(容器)在图形界面里面是一种可以容纳其它Component一种元素容器,Container也是一种Component的,Container里面还可以容纳别的Container。
Container里面又分为Window和Pannel,Window它可以独立显示,我们通常看到各种各样的东西 应用程序的窗口都可以称为Window,Window独立显示作为应用程序窗口,Pannel也可以容 纳其他图形元素,但一般看不见Pannel,Pannel不能作为应用程序的独立窗口显示,Pannel要想 显示时,你必须把自己放进去Window只能在里面显示。
Pannel典型的应用是Applet( JAVA页面小应用程序),现在基本不用了,A JAX和JAVASCRIPT完全取代了它的应用。
Window本身也可以分为Frame和Dialog,Frame是我们平时看到的一般窗口,Dialog需要用户进行某些操作(如点击下拉菜单项目)的对话框,即Dialog。
二、组件和容器(Component和Container)
2.1. Frame
【Frame范例】
package com.kuang; import java.awt.*; //学习JAVA的GUI编程编写的第一个图形界面窗口 public class TestFrame {
public static void main(String[] args) {
///这里只在内存中创建了一个窗口对象 我们看不出来。 Frame frame = new Frame("我的第一个JAVA图形界面窗口"); ///设置窗体的背景颜色 frame.setBackground(Color.blue); ///设置窗体是否可见 ///想看到内存中创建的窗口对象 //必须调用setVisble()方法 以及参数true只有通过传入才能看到窗体 //如果输入的参数是false ///那么窗户也是看不见的。 frame.setVisible(true); //设置窗体的初始大小
frame.setSize(400,400);
//设置窗体出现时的位置,如果不设置则默认在左上角(0,0)位置显示
frame.setLocation(200,200);
// 设置窗体能否被改变大小
// 设置为false后表示不能改变窗体的显示大小
// 这里将窗体显示的大小设置为200X200
// 那么窗体的显示只能是这个大小了,不能再使用鼠标拖大或者缩小
frame.setResizable(false);
}
}
运行结果:
【发现问题:关闭不掉,解决方法:停止Java程序的运行】
【演示二:展示多个窗口】
package com.kuang; import java.awt.*; public class TestMultiFrame { public static void main(String[] args) { MyFrame f1 = new MyFrame( 100, 100, 200, 200, Color.blue ); MyFrame f2 = new MyFrame( 300, 100, 200, 200, Color.yellow ); MyFrame f3 = new MyFrame( 100, 300, 200, 200, Color.red ); MyFrame f4 = new MyFrame( 300, 300, 200, 200, Color.MAGENTA ); } } //
自定义一个类MyFrame,并且从Frame类继承 //这样MyFrame类就拥有了Frame类的一切属性和方法 //并且MyFrame类还可以自定义属性和方法 //因此使用从Frame类继承而来的自定义类来创建图形窗口比直接使用Frame类来创建图形窗口要灵活 //所以一般使用从Frame类继承而来的自定义类创建图形窗口界面比较好, //不推荐直接使用Frame类来创建图形窗口界面 class MyFrame extends Frame { //定义一个静态成员变量id,用来记录创建出来的窗口的数目 static int id = 0; //自定义构成方法,在构造方法体内使用super调用父类Frame的构造方法 public MyFrame(int x, int y, int w, int h, Color color) { super( "MyFrame" + (++id) ); setBackground( color ); setLayout( null ); setBounds( x, y, w, h ); setVisible( true ); } }
运行结果:
2.2. Panel
【演示】
package com.kuang;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame( "JAVA Frame With Panel" );
Panel panel = new Panel( null );
frame.setLayout( null );
//这里设置的坐标(300,300)是相对于整个屏幕的
frame.setBounds( 300, 300, 500, 500 );
//设置背景颜色时使用三基色(红,绿,蓝)的比例来调配背景色
frame.setBackground( new Color( 0, 0, 102 ) );
//这里设置的坐标(50,50)是相对于Frame窗体的
panel.setBounds( 50, 50, 400, 400 );
panel.setBackground( new Color( 204, 204, 255 ) );
//把Panel容器装入到Frame容器中,使其能在Frame窗口中显示出来
frame.add( panel );
frame.setVisible( true );
//解决关闭问题
frame.addWindowListener( new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit( 0 );
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
} );
}
}
结果如下:
三、布局管理器
3.1. 第一种布局管理器——FlowLayout
【演示】
package com.kuang;
import java.awt.*;
public class TestFlowLayout {
public static void main(String[] args) {
Frame frame = new Frame( "FlowLayout" );
//使用Button类创建按钮
// 按钮类的其中一个构造方法:Button(String label) label为按钮显示的文本
Button button1 = new Button( "button1" );
Button button2 = new Button( "button2" );
Button button3 = new Button( "button3" );
// setLayout方法的定义:public void setLayout(LayoutManager mgr)
// 使用流水(Flow)线般的布局
frame.setLayout( new FlowLayout() );
// 使用了布局管理器FlowLayout,这里的布局采用默认的水平居中模式
// frame.setLayout(new FlowLayout(FlowLayout.LEFT));
// 这里在布局的时候使用了FlowLayout.LEFT常量,这样就将按钮设置为左对齐
// frame.setLayout(new FlowLayout(FlowLayout.RIGHT));
//这里在布局的时候使用了FlowLayout.RIGHT常量,这样就将按钮设置为右对齐
frame.setSize( 200, 200 );
frame.add( button1 ); // 把创建出来的按钮放置到Frame窗体中
frame.add( button2 ); // 这里并没有设置按钮的大小与位置
frame.add( button3 ); // 设置按钮的大小与位置都是由布局管理器来做的
frame.setVisible( true );
}
}
运行结果:
3.2. 第二种布局管理器——BorderLayout
package com.kuang;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args) {
Frame frame = new Frame("TestBorderLayout");
Button buttonEast = new Button("East");
Button buttonWest = new Button("West");
Button buttonSouth = new Button("South");
Button buttonNorth = new Button("North");
Button buttonCenter = new Button("Center");
//把按钮放置到Frame窗体时按照东西南北中五个方向排列好,推荐使用这种方式去排列窗体元素
//这样容易检查出错误 因为这样写如果写错了编译器会提示出错
frame.add(buttonEast,BorderLayout.EAST);
frame.add(buttonWest,BorderLayout.WEST);
frame.add(buttonSouth,BorderLayout.SOUTH);
frame.add(buttonNorth,BorderLayout.NORTH);
frame.add(buttonCenter,BorderLayout.CENTER);
//也可以使用这样的方式排列按钮 在把按钮放置到Frame窗体时使用方向定位的字符串指定按钮的放置位置
//这种使用方向定位的字符串指定按钮的放置方式不推荐使用 一旦写错了方向字符串就不好检查出来
//因为即使是写错了仍然可以编译通过
/* frame.add(buttonEast,"EAST"); frame.add(buttonWest,"West"); frame.add(buttonSouth,"South"); frame.add(buttonNorth,"North"); frame.add(buttonCenter,"Center"); */
frame.setSize(200,200);
frame.setVisible(true);
}
}
运行结果:
3.3. 第三种布局管理器——GridLayout(表格布局管理器)
【演示】
package com.kuang;
import java.awt.*;
public class TestGridLayout {
public static void main(String[] args) {
Frame frame = new Frame( "TestGridLayout" );
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( "bnt6" );
// 把布局划分成3行2列的表格布局形式
frame.setLayout( new GridLayout( 3, 2 ) );
frame.add( btn1 );
frame.add( btn2 );
frame.add( btn3 );
frame.add( btn4 );
frame.add( btn5 );
frame.add( btn6 );
// Frame.pack()是JAVA语言的一个函数
// 这个函数的作用就是根据窗口里面的布局及组件的preferredSize来确定frame的最佳大小。
frame.pack();
frame.setVisible( true );
}
}
运行结果:
3.4. 布局练习
这几种布局管理器可以设置在Frame里面,也可以设置在Panel里面,而Panel本身也可以加入到Frame 里面,因此通过Frame与Panel的嵌套就可以实现比较复杂的布局;
【演示】
package com.kuang;
import java.awt.*;
public class TestTenButtons {
public static void main(String[] args) {
//这里主要是对显示窗体进行设置
Frame frame = new Frame( "布局管理器的嵌套使用" );
//把整个窗体分成2行1列的表格布局
frame.setLayout( new GridLayout( 2, 1 ) );
frame.setLocation( 300, 400 );
frame.setSize( 400, 300 );
frame.setVisible( true );
frame.setBackground( new Color( 204, 204, 255 ) );
//这里主要是对Panel进行布局的设置
Panel p1 = new Panel( new BorderLayout() );
//p2使用2行1列的表格布局
Panel p2 = new Panel( new GridLayout( 2, 1 ) );
Panel p3 = new Panel( new BorderLayout() );
//p4使用2行2列的表格布局
Panel p4 = new Panel( new GridLayout( 2, 2 ) );
//这里主要是把按钮元素加入到Panel里面
p1.add( new Button( "East(p1-东)" ), BorderLayout.EAST );
p1.add( new Button( "West(p1-西)" ), BorderLayout.WEST );
p2.add( new Button( "p2-Button1" ) );
p2.add( new Button( "p2-Button2" ) );
//p1里面嵌套p2,把p2里面的按钮作为p的中间部分装入到p1里面
//把p2作为元素加入到p1里面
p1.add( p2, BorderLayout.CENTER );
p3.add( new Button( "East(p3-东)" ), BorderLayout.EAST );
p3.add( new Button( "West(p3-西)" ), BorderLayout.WEST );
for (int i = 0; i < 4; i++) {
p4.add( new Button( "p4-Button" + i ) );
}
//p3里面嵌套p4,把p4里面的按钮作为p的中间部分装入到p3里面
p3.add( p4, BorderLayout.CENTER );
//把Panel装入Frame里面,以便于在Frame窗体中显示出来
frame.add( p1 );
frame.add( p3 );
}
}
运行结果 :
四、布局管理器总结
五、事件监听
【】
package com.kuang;
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent {
public static void main(String[] args) {
Frame frame = new Frame("TestActionEvent");
Button button = new Button("Press Me");
// 创建一个监听对象
MyActionListener listener = new MyActionListener();
// 把监听加入到按钮里面,监听按钮的动作,
// 当按钮触发打击事件时,就会返回一个监听对象e
// 然后就会自动执行actionPerformed方法
button.addActionListener(listener);
frame.add(button, BorderLayout.CENTER);
frame.pack();
addWindowClosingEvent(frame);
frame.setVisible(true);
}
//点击窗体上的关闭按钮关闭窗体
private static void addWindowClosingEvent(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
// 自定义Monitor(监听)类实现事件监听接口ActionListener
// 一个类要想成为监听类,那么必须实现ActionListener接口
class MyActionListener implements ActionListener{
//重写ActionListener接口里面的actionPerformed(ActionEvent e)方法
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("A Button has been Pressed");
}
}
【】
package com.kuang; import java.awt.*