一、概述
GUI(Graphical User Interface, 图形用户界面)比早期的 CLI(Command Line User Interface, 命令行用户界面)更直观。
Java为GUI提供的对象都存在java.awt和javax.swing两个包中。
java.awt:Abstract Window Toolkit(抽象窗口工具包),需要调用本地系统方法实现功能,属重量级控件。Frame Button Label TextField TextArea Panel
javax.swing:是JDK1.2以后版本引入的。它是在Awt的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由java实现。增强了移植性,属轻量级(lightweight, 即all-Java language)控件。JFrame JButton JLabel JTextField JTextArea JPanel
二、组件
组件(component):Java中构成图形用户界面的各种元素。
组件分为容器(Container)类和非容器类组件两大类。容器又分为顶层容器和非顶层容器两大类。
Component类是所有组件和容器的抽象父类,其中定义了一些每个容器和组件都可能用到的方法:
getBounds() , getSize(), getLocation(), getHeight(), getWidth()
setVisible(), setEnabled(), setBackground(), setForeground()
getGraphics(), requestFocus()
Swing组件JComponent是非顶层容器。
三、布局管理器
Java.awt包中共定义了多种布局管理器
常用的三种:FlowLayout BorderLayout GridLayout,还有CardLayout, GridBagLayout等
1.FlowLayout——Panel类的默认布局管理器
对组件逐行定位,行内从左到右,一行排满后换行。
默认对齐方式为居中对齐。
不改变组件的大小,按组件原有尺寸显示组件。
FlowLayout 的构造方法:
可在构造方法中设置不同的组件间距、行距及对齐方式
1)new FlowLayout(FlowLayout.RIGHT,20,40);
右对齐,组件之间水平间距20个像素,竖直间距40个像素;
2)new FlowLayout(FlowLayout.LEFT);
左对齐,水平和竖直间距为缺省值:5;
3)new FlowLayout();
使用缺省的居中对齐方式,水平和竖直间距为缺省值:5;
2.BorderLayout——Frame类的默认布局管理器
BorderLayout将整个容器的布局划分成东、西、南、北、中五个区域,组件只能被添加到指定的区域
如不指定组件的加入部位,则默认加入到Center区域
每个区域只能加入一个组件,如加入多个,则先前加入的组件会被遗弃
3.GridLayout
将布局划分成规则的矩形网格,每个单元格区域大小相等
组件被添加到每个单元格中,先从左到右添满一行后换行,再从上到下
在GridLayout构造方法中指定分割的行数和列数:new GridLayout(4,5);
4.CardLayout
能够帮助用户处理两个以至更多的成员共享同一显示空间,就好象一叠卡片摞在一起。
注意:在一张卡片中只能显示一个组件,因此可以使用容器嵌套方法显示多个组件
addLayoutComponent, first, next, last方法
5.GridBagLayout
AWT中最灵活、最复杂的布局管理器,各组件所占空间可以不相同且灵活规定
四、事件监听
1.概述
事件(Event):鼠标、键盘、布局改变等等操作等。
事件监听器(Event Listener):对这些事件作出响应的程序。事件监听器是一些事件的接口,是 AWTEventListener的子接口。接口中含有相关的方法,如:MouseMotionListener 是对鼠标移动事件的处理的接口,它含有两个重要的方法:
void mouseDragged (MouseEvent e);// 处理鼠标拖动的方法
void mouseMoved (MouseEvent e);// 处理鼠标移动的方法
这些方法带一个事件对象作为参数。事件参数是AWTEvent的子类。如MouseMotionListener的两个方法都带MouseEvent参数。程序中可以根据这个参数得到有关事件的详细信息。
事件类中包含有事件相关的信息,最重要的有:
(1)事件源(即产生事件的组件)
getSource()
得到的Object可以强制类型转换成相应的类型
(2)事件的具体情况
如MouseEvent 的 getX(), getY() 方法得到鼠标的坐标
KeyEvent 的 getKeyChar() 得到当前的字符等。
事件分类:包:java.awt.event 及 javax.swing.event
事件监听机制流程图
2.常用的事件类
1)对所有组件能用的事件
component listener
focus listener
key listener
mouse listener
mouse-motion listener
mouse-wheel listener …
2)对特定组件能用的事件
Action Listener
Caret Listener
Change Listener
Item Listener
List Selection Listener
Window Listener …
3.事件适配器(Adapter)----简化实现Listener
如WindowListener有7个方法,即使一些方法不做任何事情,也得书写全。
在适配器类中,实现了相应监听器接口中所有的方法,但不做任何事情。
在extends事件适配器时,只需要Override自己所需要的方法即可
常见的事件适配器:
(1)ComponentAdapter (组件适配器);
(2)ContainerAdapter (容器适配器);
(3)FocusAdapter (焦点适配器);
(4)KeyAdapter (键盘适配器);
(5)MouseAdapter (鼠标适配器);
(6)MouseMotionAdapter (鼠标运动适配器);
(7)WindowAdapter (窗口适配器)。
4.注册事件监听器
事件的注册 addxxxxListener
监听器的实现有两种方法
1)implements xxxListener
具体写其中的每个方法。实现时,可以单独写个类 (实现接口或继承Adapter),或者写在相前的类中(implements),或者匿名类,或者用Lambda表达式(Java8以上)
2)extends xxxAdapter
其中Adapter是Listener的默认实现,每个方法的方法体为空。Adapter可以只Override其中重要的方法
一个对象上可注册多个监听器,多个对象也可注册同一个监听器,用事件参数的 getSource() 可以得到是哪一个对象。
import java.awt.*;
import java.awt.event.*;
public class FrameDemo {
private Frame f;
private Button but;
FrameDemo(){
init();
}
public void init(){
f = new Frame("my frame");
//设置窗体的基本属性
f.setBounds(300,100,600,500); //x, y, width, height
f.setLayout(new FlowLayout());
//加按钮
but = new Button("my button");
f.add(but);
//加载一下窗体上事件
myEvent();
//显示窗体
f.setVisible(true);
}
private void myEvent(){
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
//让按钮具备退出程序的功能
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("Exit by button");
System.exit(0);
}
});
}
public static void main(String[] args){
new FrameDemo();
}
}
5.事件与线程
线程中,如果要更新界面,要放到the event dispatching thread,也就是要调用 SwingUtilities.invokeLater()方法。
6.实现界面的三步曲
(1)创建组件(Component)
创建组成界面的各种元素,如按钮、文本框等。
(2)指定布局(Layout)
根据具体需要排列它们的位置关系。
(3)响应事件(Event)
定义图形用户界面的事件和各界面元素对不同事件的响应, 从而实现图形用户界面与用户的交互功能。
/*
实例: 输入文件目录,显示该目录下的所有文件的文件名
*/
import java.awt.*;
import java.awt.event.*;
import java.io.File;
public class MyWindowDemo{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button okBut;
MyWindowDemo(){
init();
}
public void init(){
f = new Frame("my window");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(30);
but = new Button("Enter");
ta = new TextArea(25,70);
d = new Dialog(f,"Mention Information",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("Yes");
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent(){
okBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
d.setVisible(false);
}
});
d.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
tf.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER)
showDir();
}
});
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
showDir();
}
});
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
private void showDir(){
String dirPath = tf.getText();
File dir = new File(dirPath);
if(dir.exists() && dir.isDirectory()){
String[] names = dir.list();
for (String name: names){
ta.append(name+"\r\n");
}
}
else{
String info = "Wrong input";
lab.setText(info);
d.setVisible(true);
}
}
public static void main(String[] args){
new MyWindowDemo();
}
}
五、应用
常用组件
标签、按钮 与动作事件
JLabel Jbutton ActionListener
文本框、文本区域 与文本事件
JTextField JTextArea JPasswordField JFormattedTextField Text:istene
单、复选按钮,列表 与选择事件
JRadioButton JCheckbox JList JComboBox ItemListener
滚动条与调整事件
JScrollBar JScrollPane AdjustmentListener
画布与鼠标、键盘事件
Canvas JComponent KeyListener MouseListener
Panel与容器事件
JPanel ComponentListener
强功能的组件
JTextPane 可以编辑文本、网页、RTF
JScrollPane 能自动滚动 new JScrollPane( 组件 )
画图 可以Override 其void paint(Graphics g)
窗口、对话框
JFrame JDialog:其中的RootPane 及 ContentPane
WindowListener:窗口能关闭
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
标准对话框
JOptionPane的4种方法
showConfirmDialog — 确认对话框,提出问题,然后由用户自己来确认(按"Yes"或"No"按钮)
showInputDialog — 提示输入文本showMessageDialog — 显示信息
showOptionDialog — 组合其它三个对话框类型
JFileChooser:文件选择器
JColorChooser:颜色选择器
菜单
JMenuBar JMenu JMenuItem JPopupMenu
frame.setMenuBar(…)
工具栏
JToolbar,其中可加入按钮
/*
模仿记事本的小程序,实现了open,save 和 exit功能。
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MyMenuDemo {
private Frame f;
private MenuBar mb;
private Menu fileMenu, subMenu;
private MenuItem openItem, saveItem, closeItem, subItem;
private FileDialog openDia, saveDia;
private TextArea ta;
private File file;
MyMenuDemo(){
init();
}
public void init(){
f = new Frame("my window");
f.setBounds(300, 100, 650, 600);
mb = new MenuBar();
ta = new TextArea();
fileMenu = new Menu("File");
openItem = new MenuItem("Open");
saveItem = new MenuItem("Save");
closeItem = new MenuItem("Exit");
subMenu = new Menu("SubMenu");
subItem = new MenuItem("SubItem");
subMenu.add(subItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(subMenu);
fileMenu.add(closeItem);
mb.add(fileMenu);
f.setMenuBar(mb);
openDia = new FileDialog(f,"Open",FileDialog.LOAD);
saveDia = new FileDialog(f,"Save",FileDialog.SAVE);
f.add(ta);
myEvent();
f.setVisible(true);
}
public void myEvent(){
openItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
openDia.setVisible(true);
String dirPath = openDia.getDirectory();
String fileName = openDia.getFile();
System.out.println(dirPath+"..."+fileName);
if (dirPath == null || fileName == null)
return;
ta.setText("");
File file = new File(dirPath, fileName);
try{
BufferedReader bufr = new BufferedReader(new FileReader(file));
String line = null;
while((line = bufr.readLine()) != null){
ta.append(line+"\r\n");
}
bufr.close();
}catch(IOException ex){
throw new RuntimeException("Load failed");
}
}
});
saveItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(file == null){
saveDia.setVisible(true);
String dirPath = saveDia.getDirectory();
String fileName = saveDia.getFile();
if(dirPath == null || fileName == null)
return;
file = new File(dirPath, fileName);
}
try{
BufferedWriter bufw = new BufferedWriter(new FileWriter(file));
String text = ta.getText();
bufw.write(text);
//bufw.flush();
bufw.close();
}catch(IOException ex){
throw new RuntimeException();
}
}
});
closeItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
}
});
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
public static void main(String[] args){
new MyMenuDemo();
}
}
六、jar 包
将程序的class文件打包封装,可实现双击打开程序。
步骤:
1.给程序添加package
2.新建一个txt文件,里面编辑固定的格式:Main-Class: package名.主类名 + 回车
3.DOS命令行切换到class文件所在目录下,输入:jar -cvfm jar包名.jar txt文件名.txt package名