13、GUI
13.1计算机与用户交互方式
方式一:Graphical User Interface(图形用户接口)。
用图形的方式,来显示计算机操作的界面,这样更方便更直观。
方式二:Command line User Interface (命令行用户接口)
就是常见的Dos命令行操作。
需要记忆一些常用的命令,操作不直观。
13.2AWT、Swing和SWT
Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中。
13.2.1java.Awt
AbstractWindow ToolKit (抽象窗口工具包),需要调用本地系统方法实现功能(依赖于平台)。属重量级控件(与系统的依赖性强)。
13.2.2javax.Swing
在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件。(在任何系统下都一模一样)
13.2.3SWT
(eclipse是用纯java编写的,它的工具是用SWT界面编写的)此外观包也是基于AWT的,但是是IBM支持eclipse小组,他们独立编写的一个图形化界面外观包。在eclipse官方网站可以下载SWT外观包。将其jar包导进来,所有的组件就可以使用了。它的界面做的跟eclipse一样的。
13.3图形化界面中的组件继承关系图
13.3.1继承图简单说明
Container:为容器,是一个特殊的组件,该组件中可以通过add方法添加其他组件进来。
Lable:标签用于封装文字
图形化界面是另一个线程在执行和控制
Container常用子类:Window Panel(面板,不能单独存在。)
13.4布局管理器
容器中的组件的排放方式,就是布局。
常见的布局管理器有以下几种(在做图形化界面之前,将自己在草稿纸上,规划一下布局)
13.4.1FlowLayout(流式布局管理器)
从左到右的顺序排列。
Panel默认的布局管理器。
13.4.2BorderLayout(边界布局管理器)
位置:东,南,西,北,中
当不指定组件的位置,则它将会以整个最大面积去填充窗体,默认为居中的。添加新组件将会覆盖。
Frame、Dialog默认的布局管理器。
13.4.3GridLayout(网格布局管理器)
规则的矩阵(应用于计算器布局)
13.4.4CardLayout(卡片布局管理器)
选项卡(选项卡)
13.4.5GridBagLayout(网格包布局管理器)
非规则的矩阵
13.4.6坐标式布局
eclipse的图形化插件的使用(自动生成代码)
13.4.7多种布局混合使用
首先将窗体整体规划分成几个部分,然后添加面板(Panel),把相应的组件添加到面板上,然后设置面板的布局方式
13.5创建图形化界面
13.5.1创建图形化界面的步骤
1、 创建Frame窗体
2、 对窗体进行基本设置:大小、位置、布局等属性
3、 定义组件
4、 将组件通过窗体的add()方法添加到窗体中
5、 让窗体显示,通过setVisible(true);
13.5.2简单的窗体创建过程
• Frame f = new Frame(“mywindow”);//创建带名窗体
• f.setLayout(newFlowLayout());//设置窗体布局
• f.setSize(500,400);//设置窗体大小(x坐标,y坐标)
• f.setLocation(300,200);//设置窗体出现在屏幕的位置
• f.setVisible(true); //设置窗体可见性
13.6事件监听机制
13.6.1事件监听机制组成
l 事件源(AWT或Swing包中的图形化界面组件)
l 事件(每一个事件源都有自己特有的和共有的Event)
l 监听器(将可以触发某一个事件的多动作,都封装到Listener)
l 事件处理(我们能做的就是:引发事件后处理方式)
13.6.2事件监听机制流程图
13.6.3事件监听机制
l 确定事件源(容器或组件)
l 通过事件源对象的addXXXListener()方法将侦听器注册到该事件源上。
l 该方法中接收XXXListener的子类对象,或者XXXListener的子类XXXAdapter的子类对象。
l 一般用匿名内部类来表示。
l 在覆盖方法的时候,方法的参数一般是XXXEvent类型的变量接收。
l 事件触发后会把事件打包成对象传递给该变量。(其中包括事件源对象。通过getSource()或者,getComponent()获取。)
13.6.4示例——在窗体中通过创建按钮
import java.awt.*;
import java.awt.event.*;
class FrameDemo//简单的优化
{
//1、(一般)定义该图形中所需的组件的引用。作用于整个类,方便使用
privateFrame f;//窗体
privateButton but;//按钮
FrameDemo()//构造函数
{
init();//初始化窗体后就用图形化界面,并具有基本事件
}
public voidinit()//对图形化界面进行初始化
{
f =new Frame("my frame");//设置窗体名
//对frame进行基本设置。
f.setBounds(300,100,600,500);//距左,距右,宽,高
f.setLayout(newFlowLayout());//设置布局
but =new Button("my button");//设置按钮
//将组件添加到frame中
f.add(but);
//显示窗体之前,加载一下窗体上事件。调用事件方法
myEvent();
f.setVisible(true);//显示窗体;
}
private voidmyEvent()//事件
{
//窗体添加监听器,传入一个具体的监听对象(使用了匿名内部类)
f.addWindowListener(newWindowAdapter()
{
//关闭窗体
publicvoid windowClosing(WindowEvent e)
{
System.exit(0);
}
});
13.6.5让事件源具备功能的步骤
1、事件源是按钮。
2、那么选择哪个监听器呢?
3、通过关闭窗体示例了解到,想要知道哪个组件具备什么样的特有监听器。
4、需要查看该组件对象的功能。
5、通过查阅button的描述。发现按钮支持一个特有监听addActionListener。
13.6.6适配器的一些介绍
适配器(adapter)的出现原因只有一个:方便创建监听器对象。因为监听器中一般有多个方法,而当只需要用一个,那么我覆盖很多个很麻烦,所以它给我们提供了已有的子类,它把所有的方法都覆盖完了,我们只要继承他,并复写其中的一个方法就可以了。
ActionListener是少数没有适配器的接口(大约三个)的其中一个。且只有一个方法。另外只要方法超过三个(包含三个)的几乎都有适配器adapter。
*/
but.addActionListener(newActionListener()
{
privateint count = 1;
//复写按钮监听器的唯一一个方法,使用匿名内部类的形式,传入一个活动事件
publicvoid actionPerformed(ActionEvent e)
{
System.out.println("退出,按钮干的");
System.exit(0);//退出虚拟机
//f.add(newButton("Button-"+(count++)));
//f.setVisible(true);
//f.validate();
//System.out.println(e.getSource());
Buttonb = (Button)e.getSource();
Framef1 = (Frame)b.getParent();
f1.add(newButton("button-"+count++));
f1.validate();
}
});
}
public static void main(String[] args) //主函数做测试用
{
newFrameDemo();
}
}
13.6.7鼠标事件
java.awt.event
类 MouseEvent
public class MouseEvent
extends InputEvent指示组件中发生鼠标动作的事件。
static int | BUTTON1(鼠标左键) |
static int | BUTTON2(鼠标右键) |
static int | BUTTON3(鼠标中键) |
13.6.8示例——键盘事件与鼠标事件
import java.awt.*;//图形界面包
import java.awt.event.*;//事件处理包
class MouseAndKeyEvent
{
private Frame f;
private Button but;
private TextField tf;
MouseAndKeyEvent()
{
init();
}
public void init()
{
f = new Frame("my frame");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(20);//一个文本框指定长度为20
but = new Button("my button");
f.add(tf);
f.add(but);
myEvent();//添加事件
f.setVisible(true);//设置窗体可见
}
private void myEvent()
{
//添加窗体监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//文本框添加键盘事件
tf.addKeyListener(new KeyAdapter()
{
//键盘按下
public void keyPressed(KeyEvent e)
{
//设置文本框中的内容按下的只能是数字
int code = e.getKeyCode();
if(!(code>=KeyEvent.VK_0 && code<=KeyEvent.VK_9))
{
System.out.println(code+".....是非法的");
//屏蔽键,使得事件不能按默认的方式进行
e.consume();
}
}
});
//给按钮添加一个键盘监听。
but.addKeyListener(new KeyAdapter()
{
//键盘按下
public void keyPressed(KeyEvent e)
{
//组合键的使用方法,ctrl键是否被按下&&另外一个键
if(e.isControlDown()&&e.getKeyCode()==KeyEvent.VK_ENTER)
//System.exit(0);
System.out.println("ctrl+enter is run");
//返回按键的文本,即返回按下键的文本信息和键对应的码值
//System.out.println(KeyEvent.getKeyText(e.getKeyCode())+"...."+e.getKeyCode());
//获取键盘按下的键和键对应的码值
System.out.println(e.getKeyChar()+"...."+e.getKeyCode());
}
});
//添加按钮活动监听器,只要按钮被活动都会发生的事件,要后于鼠标监听器,此时去键盘也可以操作。
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("action ok");
}
});
*/
//按钮添加一个鼠标监听器,添加一个鼠标适配器
but.addMouseListener(new MouseAdapter()
{
private int count = 1;
private int clickCount = 1;
//鼠标进入按钮区域事件
public void mouseEntered(MouseEvent e)
{
System.out.println("鼠标进入到该组件"+count++);
}
//鼠标单击按钮事件
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount()==2)
System.out.println("双击动作"+clickCount++);
}
});
*/
}
public static void main(String[] args)
{
new MouseAndKeyEvent();
}
}
13.6.9列出指定目录内容
import java.awt.*;
import java.awt.event.*;
import java.io.*;
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(60);//列数
but = new Button("转到");
ta = new TextArea(25,70);//行数,列数
//对话框的参数信息,依赖的窗体,对话框名字,模式true为取消掉才可以操作窗体
d = new Dialog(f,"提示信息-self",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("确定");
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)
{
d.setVisible(false);//隐藏
}
});
//文本框添加事件
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())
{
ta.setText("");
String[] names = dir.list();
for(String name : names)
{
ta.append(name+"\r\n");
}
}
else
{
String info = "您输入的信息:"+dirPath+"是错误的。请重输";
lab.setText(info);
d.setVisible(true);
}
}
public static void main(String[] args)
{
new MyWindowDemo();
}
}
13.7菜单继承体系
13.7.1菜单概述
l MenuBar(菜单条/栏)Menu(菜单)MenuItem(菜单项)
l 先创建菜单条,再创建菜单,每一个菜单中建立菜单项。
l 也可以菜单添加到菜单中,作为子菜单。
l 通过setMenuBar()方法,将菜单添加到Frame中。
l 菜单是菜单项的子类。
13.7.2示例——菜单的创建
import java.awt.*;
import java.awt.event.*;
class MyMenuDemo
{
private Frame f;
private MenuBar mb;//菜单条
private Menu m,subMenu;//菜单
private MenuItem closeItem,subItem;//菜单项
MyMenuDemo()
{
init();
}
public void init()
{
f = new Frame("my window");
f.setBounds(300,100,500,600);
f.setLayout(new FlowLayout());
mb = new MenuBar();
m = new Menu("文件");
subMenu = new Menu("子菜单");//菜单有箭头,条目是没有的
subItem = new MenuItem("子条目");
closeItem = new MenuItem("退出");
subMenu.add(subItem);//子菜单中添加子菜单项
m.add(subMenu);//在菜单中添加子菜单
m.add(closeItem);//在菜单中添加菜单项
mb.add(m);//菜单条中添加菜单
f.setMenuBar(mb);//窗体中添加菜单条
myEvent();
f.setVisible(true);
}
private void myEvent()
{
//为菜单项添加活动监听
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();
}
}
13.7.3一个简单的记事本程序
package mymenu;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MyMenuTest
{
private Frame f;
private MenuBar bar;
private TextArea ta;
private Menu fileMenu;
private MenuItem openItem,saveItem,closeItem;
private FileDialog openDia,saveDia;
private File file;
MyMenuTest()
{
init();
}
public void init()
{
f = new Frame("my window");
f.setBounds(300,100,650,600);
bar = new MenuBar();
ta = new TextArea();//未设置布局,则文本区全部填充
fileMenu = new Menu("文件");
openItem = new MenuItem("打开");
saveItem = new MenuItem("保存");
closeItem = new MenuItem("退出");
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(closeItem);
bar.add(fileMenu);
f.setMenuBar(bar);
//文件对话框,关联窗体,名字,模式(打开默认、保存)
openDia = new FileDialog(f,"我要打开",FileDialog.LOAD);
saveDia = new FileDialog(f,"我要保存",FileDialog.SAVE);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
//保存文件框事件,中的保存对话框的弹出情况,当有源文件是保存不弹出;当没有源文件时保存时弹出;无论有没有,另存为都会有对话框弹出。
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();
}
}
});
//打开文本框事件
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 = 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("读取失败");
}
}
});
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 MyMenuTest();
}
}
13.8制作jar包并双击执行
如何制作可以双击执行的jar包呢?
1,将多个类封装到了一个包(package)中。
编译带包源文件 javac –d 路径 *.java
2,定义一个jar包的配置信息。
定义一个文件a.txt(随便什么都可以)。文件内容为:
Main-Class:(空格)包名.类名(回车)
说明:空格是标志性的开头,回车是结束语句,不然没有文件
3,打jar包。
jar -cvfm my.jar a.txt 包名
4,通过winrar程序进行验证,查看该jar的配置文件中是否有自定义的配置信息。
5,通过工具--文件夹选项--文件类型--jar类型文件,通过高级,定义该jar类型文件的打开动作的关联程序。
jdk\bin\javaw.exe -jar
6,双击试试!。哦了。