GUI图形用户界面
GUI
用户图形接口:用图形的方式,来显示计算机操作的界面,这样更方便更直观
CLI
命令行用户接口:就是常见的dos命令行操作,需要记忆一些常用的命令,操作不直观
java为GUI提供的对象都存在java.Awt和javax.Swing两个包中
Awt和Swing
- java.Awt抽象窗口工具包,需要调用本地系统方法实现功能,属于重量级控件
- javax.Swing在Awt的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由java实现,增强了移植性,属轻量级控件。
容器中的组件的排放方式,就是布局。
常见的布局管理器:
- FlowLayout(流式布局管理器)
- 从左到右的顺序排列
- Panel默认的布局管理器
- BorderLayout(边界布局管理器)
- 东,南,西,北,中
- Frame默认的布局管理器
- GridLayout(网格布局管理器)
- 规则的矩阵
- CardLayout(卡片布局管理器)
- 选项卡
- GridBagLayout(网格包布局管理器)
- 非规则的矩阵
那么我们开始建立一个新的窗体,
步骤是:
建立一个窗体;
设置窗体的基本属性,包括大小,位置,布局
通过add方法在窗体中添加组件
通过setVisible()里边传true值使窗体可见。
演示:
//演示基本窗体的建立
import java.awt.*;
public class FrameDemo {
public static void main(String[] args)
{
Frame f = new Frame("myFrame");//先创建一个窗体对象
f.setLayout(new FlowLayout());//设置布局方式为流式布局
f.setLocation(300,200);//设置窗体位置在距离左边300px,距离上边200px
f.setSize(500,400);//设置窗体大小为500*400
Button b = new Button("按钮1");//创建一个按钮对象
f.add(b);//将按钮对象添加进窗体中
f.setVisible(true);//将窗体设置为可见
}
}
运行结果:
注意:
Frame窗体默认的是面板式布局,就是添加进来的组件会布满整个窗体,所以这里使用了流式布局。
setVisible方法必须放在最后一行,否则有些效果出不来。
当我们在操作创建下的窗体的时候,发现,最大化最小化都可以实现,但是关闭按钮点了没有反应,窗体不会关闭,这是为什么呢?
这就设计到了事件监听机制的问题:
事件监听机制的组成:
- 事件源
- 事件
- 监听器
- 事件处理(引发事件后处理方式)
事件源:就是Awt包或者Swing包中的那些图形化界面组件
事件:每一个事件源都有自己特有的对应事件和共性事件。
监听器:将可以触发某一个事件的动作(不止一个动作)都封装到了监听器中,
以上三者,在java中都已经定义好了,直接获取拿来用就可以了
我们要做的就是对产生的动作进行处理。
//演示基本窗体的建立
import java.awt.*;
import java.awt.event.*;
public class FrameDemo {
public static void main(String[] args)
{
Frame f = new Frame("myFrame");//先创建一个窗体对象
f.setLayout(new FlowLayout());//设置布局方式为流式布局
f.setLocation(300,200);//设置窗体位置在距离左边300px,距离上边200px
f.setSize(500,400);//设置窗体大小为500*400
Button b = new Button("按钮1");//创建一个按钮对象
f.add(b);//将按钮对象添加进窗体中
//给窗体添加一个事件监听器
f.addWindowListener(new WindowAdapter()//传进来一个事件监听器WindowListener但是这里边有7个抽象方法,
{
//WindowAdapter实现了WindowListener接口,而且覆盖了所有的方法
//可以直接拿过来创建匿名内部类进行方法的复写
//关闭窗口的方法
public void windowClosing(WindowEvent e)//当事件发生的时候,调用该方法
{
System.out.println("关闭");
System.exit(0);
}
//当窗口被打开的时候调用
public void windowOpened(WindowEvent e)
{
System.out.println("打开窗体");
}
//当窗口获得焦点的时候会自动调用
public void windowActivated(WindowEvent e)
{
System.out.println("激活窗口");
}
});
f.setVisible(true);//将窗体设置为可见
}
}
运行结果:
窗口可以直接被关闭,而且控制台上会有数据打印出来。
其实加监听器的方法就是先给窗体调用添加监听器的方法addWindowListener
同时参数要传进去一个WindowListener对象,可是WindowListener是一个接口,
发现了WindowListener有一个子类,WindowAdapter实现了WindowListener接口,并且复写了WindowListener所有的方法,而且方法体都是空的,
但是WindowAdapt是一个抽象的类,不可以创建对象,
于是用内部类的方式,复写里边的方法
每一个处理方法被调用的时候,都要有个事件传进来。
//规范化书写,将窗体布局的设置和添加监听器分离开
//给按钮添加监听器,能够关闭掉窗体
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
Frame f = null;
Button b = null;
public void inis()
{
f = new Frame("我的窗体");
b = new Button("关闭");
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(b);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//通过按钮关闭窗体
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("关闭,按钮干的");
System.exit(0);
}
});
}
}
public class FrameDemo2 {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果:
操作成功,为什么WindowListener需要有Adapter(适配器)呢?而按钮监听器不用呢?
这是因为,Window上边的监听器(接口)中的方法有7个,要是一个一个去复写,很累的,所以就出现了适配器,适配器覆盖了所有的方法但是方法体为空的,我们使用适配器,用哪个方法就复写哪个方法,很方便的。
但是在按钮的监听器中,只有一个方法,actionPerformed,所以用不着适配器。
鼠标事件:
在按钮上添加鼠标活动事件:
实例如下:
//规范化书写,将窗体布局的设置和添加监听器分离开
//给按钮添加鼠标监听器
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
Frame f = null;
Button b = null;
public void inis()
{
f = new Frame("我的窗体");
b = new Button("关闭");
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(b);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//鼠标进入按钮监听器
b.addMouseListener(new MouseAdapter()
{
int count = 1;
public void mouseEntered(MouseEvent e)
{
System.out.println("鼠标进入按钮区域:"+count++);
}
});
//鼠标点击事件监听器
b.addMouseListener(new MouseAdapter()
{
int count = 1;
public void mouseClicked(MouseEvent e)
{
System.out.println("鼠标点击"+count++);
}
});
//MouseEvent中有可以获取鼠标点击次数的方法int getClickCount()
//可以用来设置单击双击事件。
//也可以设置动作监听器:
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("action run");
}
});
}
}
public class FrameDemo3 {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果:
结果可以发现,在给按钮同时加上鼠标监听器和动作监听器之后,点击一次鼠标,是鼠标监听器先执行,
这是因为鼠标监听事件更具体一些,所以先执行。
给按钮添加键盘监听事件:
//规范化书写,将窗体布局的设置和添加监听器分离开
//给按钮添加键盘监听器
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
Frame f = null;
Button b = null;
public void inis()
{
f = new Frame("我的窗体");
b = new Button("关闭");
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(b);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
System.out.println(KeyEvent.getKeyText(e.getKeyCode()));
//getKeyCode方法可以根据键盘键入的值获取到相应的int类型的值
//getKeyText方法可以根据传入的int类型的值获取到键盘上的文字形式的字符串
}
});
}
}
public class FrameDemo3 {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果为:
然后演示一个扣扣号的输入框:
需求是:一个输入框,只能输入数字,如果输入其他字符,则提示这个字符是非法的,而且该非法字符不可以写入到输入框中:
//一个扣扣输入框,只能输入数字
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
Frame f = null;
TextField tf = null;
Button b = null;
public void inis()
{
f = new Frame("QQ窗体");
b = new Button("登陆");
tf = new TextField(15);//新建一个文本框,列数为15
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(tf);
f.add(b);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
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("输入的字符是非法的");
//默认是键盘一敲就文字就会到了输入框中,
//consume方法就是改变这种默认的方式。
e.consume();
}
}
});
}
}
public class MouseAndKeyTest {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果为:
演示组合键怎么读取的:
//组合键的使用
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
Frame f = null;
Button b = null;
public void inis()
{
f = new Frame("我的窗体");
b = new Button("关闭");
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(b);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
b.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
//判断Ctrl键是否已经按下,和按键是否为Enter键
if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER)
System.out.println("Control + enter run ");
}
});
}
}
public class FrameDemo4 {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果:
练习:列出指定的目录中的内容:
//列出指定目录下的文件名称
//具体是:在最上方的文本框中输入一个目录,然后在下方的文本区域中输出该目录下的所有文件
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class MyFrame
{
MyFrame()
{
inis();
}
//在外边建立所有对象的引用,省的等会找不到还是怎么的
Frame f = null;
Button b = null;
TextField tf = null;
TextArea ta = null;
//从这里开始定义的是弹出错误对话框的对象
Dialog d = null;
Label l = null;
Button but = null;
public void inis()
{
f = new Frame("我的Window");
b = new Button("转到");
tf = new TextField(55);
ta = new TextArea(40,62);
f.setBounds(300,200,500,400);//该方法取代的setSize和setLocation设置的值分别表示横坐标,纵坐标,宽和高
f.setLayout(new FlowLayout());
f.add(tf);
f.add(b);
f.add(ta);
myListener();//该方法可以添加进来全部的监听器
f.setVisible(true);
}
//这里添加监听器
public void myListener()
{
//关闭键关闭窗体的监听器
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//给转到按钮添加时间监听器
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDir();
}
});
//键盘监听器,输完目录之后按回车可以直接显示出目录中的文件
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(KeyEvent.VK_ENTER==e.getKeyCode())
{
showDir();
}
}
});
}
//这里封装的是按照文本框中输入的目录获取到目录下的文件的方法
private void showDir()
{
//每一次列出目录的时候,都把文本区域中的数据清空
ta.setText("");
String line = tf.getText();
File dir = new File(line);
//判断如果存在,而且文件是目录,则写入数据,如果不是目录,或者目录不存在,弹出对话框
if(dir.exists() && dir.isDirectory())
{
String[] names = dir.list();
for(String name:names)
{
ta.append(name+"\r\n");
}
}
else
{
d = new Dialog(f,"温馨提示",true);
l = new Label();
but = new Button("确定");
d.setBounds(500,400,270,100);
d.setLayout(new FlowLayout());
d.add(l);
d.add(but);
String s = "对不起,您输入的内容"+line+"有误,请重输";
l.setText(s);
//点关闭按钮可以使对话框关闭
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
//鼠标点击按钮可以使对话框关闭
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
//按回车键可以使对话框关闭
but.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
d.setVisible(false);
}
});
but.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
d.setVisible(false);
}
});
d.setVisible(true);
}
tf.setText("");//将目录中的文件输入文本区域后就把文本框中的数据清空
}
}
public class MyWindowDemo {
public static void main(String[] args)
{
new MyFrame();
}
}
运行结果:
当输入正确的目录之后是这样的结果:
当输入错误的目录之后是这样的结果:
图形化界面中的菜单
MenuBar菜单栏,用窗体的setMenuBar方法添加,而不是add方法
Menu:菜单,用MenuBar对象调用add方法添加进菜单栏中
MenuItem:条目,菜单中的一个一个的选项。
演示:
//菜单条的添加演示
import java.awt.*;
import java.awt.event.*;
class MenuDemo
{
MenuDemo()
{
isit();
}
private Frame f = null;
private MenuBar mb = null;
private Menu m1 = null;
private Menu m2 = null;
private MenuItem mi1= null;
private MenuItem mi2= null;
private MenuItem mi3= null;
private MenuItem mi4= null;
private MenuItem mi5= null;
public void isit()
{
f = new Frame("我的菜单");
mb = new MenuBar();
m1 = new Menu("文件");//这是一个菜单
m2 = new Menu("新建");//这是一个菜单中的子菜单,下边还有条目
mi1 = new MenuItem("打开");//这是文件菜单中的条目
mi2 = new MenuItem("保存");
mi3 = new MenuItem("退出");
mi4 = new MenuItem("java");//这是子菜单中的子条目中的内容
mi5 = new MenuItem("文本文件");
f.setBounds(400,300,400,300);
f.setLayout(new FlowLayout());
f.setMenuBar(mb);//使用这个方法添加MenuBar菜单栏,而不是用add方法
mb.add(m1);
m1.add(m2);
m2.add(mi4);
m2.add(mi5);
m1.add(mi1);
m1.add(mi2);
m1.add(mi3);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
//点关闭按钮可以关掉窗体
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//菜单中的退出条目,可以结束窗体
mi3.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
public class MyMenuDemo {
public static void main(String[] args)
{
new MenuDemo();
}
}
运行结果:
文件对话框的使用:
保存文件和打开文件:
实例:
//练习,打开文件,和保存文件的过程
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class MenuDemo
{
MenuDemo()
{
isit();
}
private Frame f = null;
private MenuBar mb = null;
private Menu m1 = null;
private Menu m2 = null;
private MenuItem mi1= null;
private MenuItem mi2= null;
private MenuItem mi3= null;
private MenuItem mi4= null;
private MenuItem mi5= null;
private TextArea ta =null;
private FileDialog open = null;
private FileDialog save = null;
private File file=null;
public void isit()
{
f = new Frame("我的菜单");
mb = new MenuBar();
m1 = new Menu("文件");//这是一个菜单
m2 = new Menu("新建");//这是一个菜单中的子菜单,下边还有条目
mi1 = new MenuItem("打开");//这是文件菜单中的条目
mi2 = new MenuItem("保存");
mi3 = new MenuItem("退出");
mi4 = new MenuItem("java");//这是子菜单中的子条目中的内容
mi5 = new MenuItem("文本文件");
ta = new TextArea();
open = new FileDialog(f,"我的打开",FileDialog.LOAD);
save= new FileDialog(f,"我的保存",FileDialog.SAVE);
f.setBounds(300,200,600,500);
f.setMenuBar(mb);//使用这个方法添加MenuBar菜单栏,而不是用add方法
mb.add(m1);
m1.add(m2);
m2.add(mi4);
m2.add(mi5);
m1.add(mi1);
m1.add(mi2);
m1.add(mi3);
f.add(ta);
myEvent();
f.setVisible(true);
}
public void myEvent()
{
//点关闭按钮可以关掉窗体
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//菜单中的退出条目,可以结束窗体
mi3.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
//想要在点打开的时候,弹出一个文件对话框来:
mi1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
open.setVisible(true);
//FileDialog对象获取到打开的文件的目录和文件名
String dirPath = open.getDirectory();
String fileName = open.getFile();
//如果这个时候点了取消,返回的值都是空的,容易造成空指针异常,这里如果都为空就什么都不做
if(dirPath==null || fileName==null)
return;
BufferedReader bufr = null;
ta.setText("");//每一次读取之前把ta里边的数据清空
try
{
file = new File(dirPath+fileName);
bufr = new BufferedReader(new FileReader(file));
String line = null;
while((line = bufr.readLine())!=null)
{
ta.append(line+"\r\n");
}
}
catch (IOException ex)
{
throw new RuntimeException("文件读取失败");
}
finally
{
if(bufr!=null)
try
{
bufr.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
});
//想要在点保存的时候,弹出一个保存的对话框
mi2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
save.setVisible(true);
save.setVisible(true);
String dirPath = save.getDirectory();
String fileName = save.getFile();
if(dirPath==null || fileName==null)
return;
file = new File(dirPath+fileName);
BufferedWriter bufw = null;
try
{
bufw = new BufferedWriter(new FileWriter(file));
String text = ta.getText();
bufw.write(text);
bufw.flush();
}
catch (IOException ex)
{
throw new RuntimeException("数据写入异常");
}
finally
{
if(bufw!=null)
{
try
{
bufw.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
});
}
}
public class MyMenuDemo {
public static void main(String[] args)
{
new MenuDemo();
}
}
运行结果可以实现,文件的LOAD和SAVE
jar包双击执行
想要将写好的程序可以双击就执行的,就像某一个软件一样的,
我们以前学过的jar命令,将类文件编译到指定的文件夹。
javac -d e:\others\myclass MyMenuDemo.java
将类文件编译到指定的包中
在和mymenu包同级目录下,创建一个文本文件,取名为1.txt
里边写上:
jar -cvfm my.jar 1.txt mymenu
将指定的包打成jar包
这样的话就可以双击执行了。