概述
两种交互界面
java.Awt和javax.Swing
继承关系图
布局
- 从左到右的顺序排列(自动)。
- Panel默认的布局管理器。
- 东,南,西,北,中。默认居中。如果不指定组件的方位,组件会以整个最大面积填充窗体
- Frame、Dialog默认的布局管理器。
- 规则的矩阵,应用计算器
- 选项卡。例子:右键-->属性
- 非规则的矩阵,一个组件占多个格子
Frame
Window常用子类:Frame Dialog
- 创建frame窗体
- 对窗体进行基本设置。比如大小,位置,布局
- 定义组件
- 将组建通过窗体的add方法添加到窗体中
- 让窗体显示,通过setVisible(true)方法
package GUITest;
import java.awt.*;
public class FrameDemo {
public static void main(String[] args) {
Frame f = new Frame("my awt");//创建一个窗体实例,默认不可见,参数是窗体标题。默认的布局管理器是边界式布局
f.setSize(500,400);//设置窗体大小,参数是横坐标和纵坐标
f.setLocation(300,200);//设置窗体位置,参数是左上角与屏幕左边和右边的距离
f.setLayout(new FlowLayout());//设置窗体的布局为流式布局
Button b = new Button("按钮");//创建一个按钮实例
f.add(b);//将按钮添加到窗体
f.setVisible(true);//设置窗体可见
}
}
事件监听机制
事件监听机制的组成
事件(Event):每一个事件源都有自己特有的事件和共性事件(比如鼠标键盘事件)
监听器(Listener):将可以触发某一事件(比如窗口事件)的动作(不止一个动作,比如杀人事件,可以有很多种动作)都已经封装到了监听器中。这样可以完全由监听器负责事件的处理
事件监听机制流程图
窗体事件
package GUITest;
import java.awt.*;
import java.awt.event.*;//需要单独导入event包
public class FrameDemo {
public static void main(String[] args) {
Frame f = new Frame("my awt");
f.setSize(500,400);
f.setLocation(300,200);
f.setLayout(new FlowLayout());
Button b = new Button("按钮");
f.add(b);
//f.addWindowListener(new MyWin());//将监听器注册到事件源
//匿名内部类实现方式
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
//窗体前置动作
public void windowActivated(WindowEvent e){
System.out.println("我活了");;
}
//窗体打开动作
public void windowOpened(WindowEvent e){
System.out.println("我被打开了");;
}
});
f.setVisible(true);
}
}
class MyWin extends WindowAdapter{
//覆盖父类中的方法,此动作一执行就会产生一个窗体事件,所以这里接受了一个窗体事件对象
public void windowClosing(WindowEvent e){//WindowAdapter类和WindowEvent类在awt包的event子包中,所以需要单独导入。
//System.out.println("window closing!"+e.toString());//打印事件信息。frame0代表当前Frame的编号
System.exit(0);//动作执行,事件触发,程序退出
}
}
Action事件
package GUITest;
import java.awt.*;
import java.awt.event.*;
public class FrameDemo {
//定义该图形界面中所需组件的引用。这样引用可以作用于整个类。
private Frame f;
private Button but;
FrameDemo(){
//加载init函数,对象一初始化就有了图形界面并具备了基本事件
init();
}
//init方法专门对图形界面初始化,不加事件,将事件与图形化组件分离
public void init(){
f = new Frame("my frame");
//对frame进行基本设置
f.setBounds(300,100,500,400);//移动组件并调整其大小,统一设置Size和Location。
f.setLayout(new FlowLayout());
but = new Button("my button");
//将组件添加到frame中
f.add(but);
//加载一下窗体上的事件
myEvent();
//显示窗体
f.setVisible(true);
}
private void myEvent(){
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
//让按钮具备退出程序的功能
/*
* 按钮就是事件源
* 那么选择哪个监听器呢?
* 通过关闭窗体事例了解到,想要知道该组件具备什么样的特有监听器,就要查看该组件对象的功能。
* 通过查阅button描述,发现按钮支持添加一个特有监听addActionListener
* ActionListener是一个少数没有适配器的接口
*/
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){//这里接受一个Action事件
System.exit(0);
}
});
}
public static void main(String[] args){
new FrameDemo();
}
}
鼠标事件
private void myEvent(){
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
//在button上添加一个Action监听器,按钮只要被活动就能执行,鼠标键盘都能让按钮活动。但是click事件会先执行,因为点击动作更具体
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("action ok");
}
});
//在button上添加一个鼠标监听器
but.addMouseListener(new MouseAdapter(){
int count=0;
//鼠标进入动作,触发鼠标事件
public void mouseEntered(MouseEvent e){
System.out.println("mouse entered the component"+count++);
}
});
but.addMouseListener(new MouseAdapter(){
//鼠标点击动作,触发鼠标事件
public void mouseClicked(MouseEvent e){
//鼠标双击。鼠标的点击次数,左右键等信息属于鼠标事件内的东西,所以要在MouseEvent类中找
if(e.getClickCount()==2)
System.out.println("mouse was double clicked");
}
});
}
键盘事件
package GUITest;
import java.awt.*;
import java.awt.event.*;
public 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,500,400);
f.setLayout(new FlowLayout());
//创建一个文本框对象,指定列数为20列
tf = new TextField(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);
}
});
//给button添加一个键盘监听器,当该按钮是当前事件源(有虚线标识)的时候,键盘按键会触发键盘事件
but.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
//获取键的字符和码
//System.out.println(e.getKeyChar()+"..."+e.getKeyCode());
//根据键盘码获取键的文本,getKeyText是一个静态方法
//System.out.println(KeyEvent.getKeyText(e.getKeyCode()));
//按下esc键,程序退出
/*
if(e.getKeyCode()==KeyEvent.VK_ESCAPE)//VK_ESCAPE是KeyEvent类的静态常量,不需要记住对应的码值
System.exit(0);
*/
//判断组合键:ctrol+enter,用到了KeyEvent的父类InputEvent的isControlDown方法
if(e.isControlDown()&&e.getKeyCode()==KeyEvent.VK_ENTER)
System.out.println("control+enter is run");
}
});
//给文本框添加一个键盘监听器,判断键盘的输入值,在0至9之间,为了不让非法文本进入文本框,需要取消事件
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();//对键进行屏蔽,consume方法是InputEvent类,该方法使用此事件,以便不会按照默认的方式由产生此事件的源代码来处理此事件。
}
}
});
}
public static void main(String[] args){
new MouseAndKeyEvent();
}
}
列出指定目录内容
对话框Dialog
package GUITest;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
//实现类除了在类中建立窗体引用,创建对象外,也可以直接继承Frame,然后直接创建窗体子类对象
public class MyWindowDemo {
private Frame f;
private Button but;
private TextField tf;
private TextArea ta;
//窗体对象引用,这里是为了方便阅读,但是为了优化内存,不需要窗体一产生Dialog对象就存在,没有意义,不该先有的对象先不创建。
private Dialog d;
//封装文字的Label对象引用
private Label lab;
//对话框按钮对象引用
private Button okBut;
MyWindowDemo(){
init();
}
public void init(){
f = new Frame("my frame");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
but = new Button("switch to");
tf = new TextField(60);
ta = new TextArea(25,70);//参数顺序:行,列
//初始化对话框对象及其组件
d = new Dialog(f,"information:self",true);//参数:依赖的窗体,模式为true:不操作对话框,所属窗体操作不了。
d.setBounds(300,100,240,150);
d.setLayout(new FlowLayout());
lab = new Label();//label此时没有传入信息,因为初始化时还不知道显示什么信息
okBut = new Button("ok");
//在对话框中添加组件
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent() {
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
//给按钮添加action监听,而不是鼠标监听,这样键盘也能监听到
but.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
showDir();
}
});
//给对话框添加监听器
d.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
d.setVisible(false);//关闭对话框,就将其设为不显示
}
});
//给对话框的按钮添加监听器
okBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
d.setVisible(false);//关闭对话框,就将其设为不显示
}
});
//给文本框添加监听器,输入文本之后按回车就能输出内容
tf.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER)
showDir();
}
});
}
//将功能进行封装,优化代码复用性
private void showDir() {
/*String text = tf.getText();//获取文本框文本,getText方法在父类TextComponent类中
ta.setText(text);//往文本区域填充数据
tf.setText("");//清空文本框
*/
//获取目录
String dirPath = tf.getText();
//将目录封装为文件对象
File dir = new File(dirPath);
//做健壮性判断,如果文件存在并且是一个目录
if(dir.exists()&&dir.isDirectory()){
ta.setText("");//清空文本区域,这样区域中只显示该目录的内容
String[] names = dir.list(); //只需要名字,所以用list方法就行了,不需要listFiles方法
for(String name:names)
//ta.setText(name+"\r\n");//加入回车符,但是这样会覆盖最终只显示一个文件
ta.append(name+"\r\n");//追加文本
}
else{
String info = "Your infor:"+dirPath+" is wrong,please enter again!";
lab.setText(info);//设置对话框中的信息
d.setVisible(true);//显示对话框,对话框大小应根据文本大小显示,应先获取组件大小,超出长度边框自动延长
}
}
public static void main(String[] args) {
new MyWindowDemo();
}
}
菜单
java.awt包中的MenuBar类package GUITest;
import java.awt.*;
import java.awt.event.*;
public 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 frame");
f.setBounds(300,100,500,600);
f.setLayout(new FlowLayout());
//初始化菜单条
mb = new MenuBar();
//初始化菜单,设置名称为File
m = new Menu("File");
//初始化子菜单
subMenu = new Menu("Sub Menu");
//初始化退出菜单项,设置名称为exit
closeItem = new MenuItem("Exit");
//初始化子菜单项
subItem = new MenuItem("Sub Item");
//在子菜单中添加子菜单项
subMenu.add(subItem);
//在菜单中添加子菜单
m.add(subMenu);
//在菜单中添加退出菜单项
m.add(closeItem);
//菜单条添加菜单
mb.add(m);
f.setMenuBar(mb);
myEvent();
f.setVisible(true);
}
private void myEvent(){
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
//给菜单项添加活动监听器
closeItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
new MyMenuDemo();
}
}
打开文件
需要使用FileDialog类,它是Dialog的子类- parent - 对话框的所有者
- title - 对话框的标题;接受 null 值时不会抛出 NullPointerException
- mode - 对话框的模式,FileDialog.LOAD 或 FileDialog.SAVE,分别对应打开或保存模式,不传入该参数时,默认是打开模式
保存文件
package GUITest;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MyMenuTest {
private Frame f;
private TextArea ta;
private MenuBar bar;
private Menu fileMenu;
private MenuItem openItem,saveItem,closeItem;
private FileDialog openDia,saveDia;
private File file;//用于FileDialog监听器中
MyMenuTest(){
init();
}
public void init() {
f = new Frame("my frame");
f.setBounds(300,100,650,600);
//f.setLayout(new FlowLayout());//默认边界布局,这样文本框会随着窗体填充,效果更好
ta =new TextArea();
bar = new MenuBar();
fileMenu = new Menu("File");
openItem = new MenuItem("Open");
saveItem = new MenuItem("Save");
closeItem = new MenuItem("Exit");
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(closeItem);
bar.add(fileMenu);
f.setMenuBar(bar);
//创建文件对话框实例
openDia = new FileDialog(f,"my open",FileDialog.LOAD);
saveDia = new FileDialog(f,"my save",FileDialog.SAVE);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent(){
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
closeItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//给打开菜单项添加活动监听,用于打开文件对话框
openItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
openDia.setVisible(true);
//获取选择的目录和文件名,并封装成文件对象
String dirPath = openDia.getDirectory();
String fileName = openDia.getFile();
if(dirPath==null||fileName==null)
return;//如果两者任意一个为null,直接返回不做任何事情。不作判断会发生异常
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){//因为此方法内有e,这里不能命名重复
throw new RuntimeException("读取失败!");
}
}
});
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);//这里创建的file对象会直接使用于下面的代码中
}
//文件存在,直接进行输出操作,源就是文本区域中的数据
try{
BufferedWriter bufr = new BufferedWriter(new FileWriter(file));
String text = ta.getText();
bufr.write(text);
//bufr.flush();//不写flush也可以
bufr.close();
}catch(IOException ex){
throw new RuntimeException("保存错误!");
}
}
});
}
public static void main(String[] args) {
new MyMenuTest();
}
}
双击执行的jar包
DOS命令行生成JAR包
javac -d c:\myclass MyMenuTest.java,这样会在myclass目录下生成一个名为包名XXX的文件夹,里面包含了所有的class文件
然后将XXX文件夹打成jar包,在命令行中切换到文件夹所在目录,然后输入:
jar包中META-INF文件夹含有的配置信息文件:MANIFEST.MF,但是里面不能写入Main-Class属性信息jar -cvf my.jar XXX就生成了指定名称的jar包:XXX.jar(但是此时双击该jar包不能执行,还需将主函数所在类的类名告诉jar包)
需要创建一个指定清单:
新建一个text文件,随便命名(例:1.txt),然后写入:Main-Class: 包名.主类名(别掉空格,空格用于区分键和值,否则会出现IO异常),再加上回车(注意这是固定格式,代表此行结束,否则数据不会写入),保存
在Dos中操作:
jar包必须在本地注册才能使用:jar -cvfm my.jar 1.txt XXX
工具-->文件夹选项-->文件类型-->选择JAR-->高级-->添加“open”操作-->在用于执行操作的应用程序中选择命令路径并加上-jar(C:\Programming\Java\jdk1.7.0_10\bin\javaw.exe-jar)
没有Jar就新建一个,并选择图标
Eclipse生成JAR包
第一:普通类导出jar包,我说的普通类就是指此类包含main方法,并且没有用到别的jar包。
1.在eclipse中选择你要导出的类或者package,右击,选择Export子选项;
2.在弹出的对话框中,选择java文件---选择JAR file,单击next;
3.在JAR file后面的文本框中选择你要生成的jar包的位置以及名字,注意在Export generated class files and resources和Export java source files and resources前面打上勾,单击next;
4.单击两次next按钮,到达JAR Manifest Specification。注意在最底下的Main class后面的文本框中选择你的jar包的入口类。单击Finish,完成。
你可以在dos环境下,进入你的jar所在的目录,运行 java -jar 名字.jar,检测运行是否正确。
第二、你所要导出的类里边用到了别的jar包。比如说你写的类连接了数据库,用到数据库驱动包oracl.jar.。
1.先把你要导出的类按照上面的步骤导出形成jar包,比如叫test.jar
2.新建一个文件夹main,比如在D盘根目录下;
3.把test.jar和oracl.jar拷贝到main文件下,右击test.jar,解压到当前文件夹。把META-INF\MANIFEST.MF剪切到另外一个地方 (比如是桌面!) ;
4.右击oracl.jar,解压到当前文件夹。
5.在dos环境下,进入到D盘的main文件夹下,执行 jar cvfm new.jar meta-inf/manifest.mf .,不要忘了最后面的点。
6.用压缩工具打开你新生成的new.jar,用你放在桌面的META-INF\MANIFEST.MF覆盖new.jar原有。
你可以在dos环境下,进入你的jar所在的目录,运行 java -jar 名字.jar,检测运行是否正确。