黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))

font color=black size=3 face=“微软雅黑”>

1、GUI与CLI简介
  关于javaGUI与CLI——计算机与用户交互的2种方式。
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第1张图片
  java.Awt包与java.Swing包的区别:Awt比较依赖于平台,跨平台性不是特别好。由于Swing是基于Awt包开发的,我们这一部分主要讲Awt包的使用。
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第2张图片
  图形化界面的各类关系图:
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第3张图片

2、布局
  对于图形界面的制作,首先我们需要对局面进行布局,常见的布局管理器如下:(22-02,通过画图的方式对各类布局进行说明)。最方便的布局方式是坐标式布局。(其实现在已经有很多工具,使得图形化见面的编辑十分简单)
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第4张图片
  如果我们的图形化界面是由多种布局来完成的,我们先设计窗体的布局,然后在窗体中添加panel面板,再对不同的面板使用不同的布局。(22-02,9.00)

3、Frame界面的创建以及事件监听机制
  我们首先说一下重点部分——事件监听机制(22-04,3.20)
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第5张图片
  事件监听机制的流程图如下:注意结合视频理解监听器的原理。
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第6张图片
  事件监听机制4个部分的作用如下:

事件源:就是awt包或者swing包中的那些图形界面组件。
	
事件:每一个事件源都有自己特有的对应事件和共性事件。

监听器:将可以触发某一个事件的动作(不只一个动作)都已经封装到了监听器中。

以上三者,在java中都已经定义好了,直接获取其对象来用就可以了。我们要做的事情是,就是对产生的动作进行处理。

  创建一个窗体的具体思路如下:

创建图形化界面:
1、创建frame窗体;
2、对窗体进行基本设置,比如大小,位置,布局,颜色等;
3、使用监视器为窗体添加动作;
4、定义组件并为组件添加相应功能;
5、使用监视器为组件添加动作;
6、将组件通过窗体的add方法添加到窗体中。
7、让窗体显示,通过setvisible(true)

  Frame窗口的创建以及监听器设置示例如下:

package pack;
import java.awt.*;
import java.awt.event.*;


class AwtDemo
{
	public static void main(String[] args) {
		//首先创建Frame窗口并设置其基本信息
		Frame fr = new Frame("my frame");
		fr.setSize(300,200);
		fr.setLocation(300,200);
		fr.setLayout(new FlowLayout());
		//接下来添加按钮
		Button bt = new Button("my button");
		fr.add(bt);//添加按钮到Frame
		
		//设置窗口的监听器
		//由于WindowListener为抽象接口,如果我们使用匿名内部类重写这个接口,其要复写的方法太多(实现接口就必须将接口所有的抽象方法实现,或者实现接口的类设置为抽象类),我们使用它的抽象子类WindowAdapter来替代,同样复写WindowAdapter的相关方法,而且由于WindowAdapter中复写了WindowListener的抽象方法,但是复写的方法为空,且不再是抽象方法,它虽然是抽象类但是它本身没有抽象方法。因此我们再继承WindowAdapter的时候,就可以重写我们需要的方法,而不需要重写所有的方法或者将子类设置为抽象类		
		//因为WindowAdapter类所有方法都是空,创建对象也没有意义,因此将其设置为抽象类
		fr.addWindowListener(new WindowAdapter() {
			//void windowActivated(WindowEvent e) 激活窗口时调用。此方法既是将窗口前置(22-05,3.00分析)
			public void windowActivated(WindowEvent e)
			{
				System.out.println("窗口激活");
			}
			
			//void windowOpened(WindowEvent e) 已打开窗口时调用。 
			public void windowOpened(WindowEvent e)
			{
				System.out.println("窗口打开");
			}
			
			//void windowClosing(WindowEvent e) 窗口正处在关闭过程中时调用。 
			public void windowClosing(WindowEvent e)
			{
				System.out.println("窗口关闭");
				System.exit(0);
			}
		});
		
		fr.setVisible(true);//设置按钮可见
	}
}
/*
class MyWin implements WindowListener
{
	//覆盖7个方法。可以我只用到了关闭的动作。
	//其他动作都没有用到,可是却必须复写。

}

因为WindowListener接口的子类WindowAdapter已经实现了WindowListener接口。
WindowAdapter:接收窗口事件的抽象适配器类。此类中的方法为空。此类存在的目的是方便创建侦听器对象。大部分监听器都有Adapter适配器,方便创建监听器。
并覆盖了其中的所有方法(覆盖的方法为空,既没有添加内容)。那么我只要继承自Windowadapter覆盖我需要的方法即可,不需要覆盖所有的方法
下面是不使用匿名内部类的常规使用方法——就只有一个方法,使用匿名内部类实现较好。
class MyWin extends WindowAdapter
{
	public void windowClosing(WindowEvent e)
	{
		//System.out.println("window closing---"+e.toString());
		System.exit(0);
	}
}
fr.addWindowListener(new MyWin());
*/


/*结果:
控制台打印
窗口激活
窗口打开
并出现窗口,我们按×,窗口关闭并在控制台打印:窗口关闭
*/

4、窗体创建以及监听器设置练习
  练习的描述与代码如下,注意这种写代码的格式


package pack;
import java.awt.*;
import java.awt.event.*;

public class FrameDemo
{
	//首先创建Frame与Button的引用
	private Frame fr;
	private Button bt;
	//在构造方法中,调用一个方法为其初始化并构造组件
	FrameDemo()
	{
		init();
	}
	//创建方法为Frame与Button初始化并构造组件——此方法不需要被外界知道,设置为private
	private void init()
	{//这里可以为窗体与按钮命名
		fr = new Frame("my frame");
		bt = new Button("my button");
		
		//对frame进行基本设置。
		//setBounds相当于setSize与setLocation2个方法
		fr.setBounds(300, 100, 600, 500);//设置位置与大小
		//如果不设置布局,Frame会有自己默认的布局管理器——边界式布局
		fr.setLayout(new FlowLayout());//设置窗体的布局为流式布局
		//将按钮添加到窗体中来
		fr.add(bt);
		
		//加载窗体的事件
		myEvent();
		
		//设置窗体可见——注意!
		fr.setVisible(true);
	}
	
	//创建窗体事件的方法——这个方法不需要被外部知晓,设置为私有
	private void myEvent()
	{
		//首先是设置窗体的事件
		fr.addWindowListener(new WindowAdapter() 
		{
			public void windowClosing(WindowEvent e) 
			{
				//static void exit(int status):终止当前正在运行的Java虚拟机。 
				System.exit(0);			
			}
		});//让按钮具备退出程序的功能
		
/*
按钮就是事件源。
那么选择哪个监听器呢?
通过关闭窗体示例了解到,想要知道哪个组件具备什么样的特有监听器,需要查看该组件对象的功能。
通过查阅button的描述。发现按钮支持一个特有监听addActionListener。
*/
		//public void addActionListener(ActionListener l)添加指定的动作侦听器,以接收发自此按钮的动作事件。
		bt.addActionListener(new ActionListener() {
			//复写ActionListener的actionPerformed的方法
			public void actionPerformed(ActionEvent e) {
				//设置按钮的功能为程序退出
				System.out.println("按钮退出");
				System.exit(0);
			}
//此处,bt是事件源、ActionEvent e是事件、actionPerformed方法是事件处理、ActionListener是监听器。
//使用监听器的时候注意4个部分不可缺少,注意了解每一个部分的用法。
		});
	}
	
	public static void main(String[] args) 
	{
		new FrameDemo();
	}
}

5、鼠标与键盘事件的监听器
  首先,鼠标事件以及其监听器的示例如下:

package pack;
import java.awt.*;
import java.awt.event.*;

public class MouseEventDemo
{
	private Frame fr;
	private Button bt;
	
	MouseEventDemo()
	{
		init();
	}
	
	//同样,创建初始化窗口的方法
	public void init()
	{
		fr = new Frame("my frame");
		bt = new Button("my button");
		
		//设置窗体
		fr.setBounds(300,100,600,500);
		fr.setLayout(new FlowLayout());
		//将按钮添加到窗体
		fr.add(bt);
		
		//添加时间监听器的方法
		myEvent();
		
		//使得窗体可见
		fr.setVisible(true);
	}
	
	//创建时间监听器的方法
	private void myEvent()
	{
		//添加窗体的监听器,使得窗体点“×”关闭,使用窗体监听器WindowListener的适配器抽象类WindowAdapter
		fr.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		
		/*
		//添加按钮的动作
		bt.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				System.out.println("action ok");
			}
		});
		我们发现用键盘使得按钮活动,也会执行ActionEvent
		按钮只要被活动,这个ActionEvent事件就会执行,而且单击的时候,鼠标动作先执行,因为其活动更加具体
		*/
		
		
		//我们给按钮添加鼠标的动作,Button从Component继承addMouseListener方法
		//public void addMouseListener(MouseListener l)添加指定的鼠标侦听器,以接收发自此组件的鼠标事件。
		//同样接口MouseListener抽象方法太多,我们使用其适配器类MouseAdapter实现
		bt.addMouseListener(new MouseAdapter() {
			//我们复写2个方法
			//void mouseEntered(MouseEvent e)鼠标进入到组件上时调用。使用count为其计数
			//void mouseClicked(MouseEvent e)鼠标按键在组件上单击(按下并释放)时调用。 使用clickCount为双击次数计数
			private int count = 1;//匿名内部类变量不可为外界使用,定义为private
			private int clickCount = 1;
			
			public void mouseEntered(MouseEvent e)
			{
				System.out.println("鼠标进入该组件的次数:"+count++);
			}
			
			public void mouseClicked(MouseEvent e)
			{
				System.out.println("单击一次");
				//使用MouseEvent事件类的int getClickCount() 返回与此事件关联的鼠标单击次数。
				//这个方法可以获取鼠标连续单击的次数,我们单击并不会激活这部分代码,只有连续双击——2次单击才会激活
				if(e.getClickCount() == 2)
					System.out.println("双击动作次数:"+clickCount++);
			}
		});
		
		
	}
	public static void main(String[] args) 
	{
		new MouseEventDemo();
	}
}

  键盘事件及其监听器在Button的应用如下

package pack;
import java.awt.*;
import java.awt.event.*;//此类中除了监听器就是事件类

public class MouseEventDemo
{
	private Frame fr;
	private Button bt;
	
	MouseEventDemo()
	{
		init();
	}
	
	//同样,创建初始化窗口的方法
	public void init()
	{
		fr = new Frame("my frame");
		bt = new Button("my button");
		
		//设置窗体
		fr.setBounds(300,100,400,200);
		fr.setLayout(new FlowLayout());
		//将按钮添加到窗体
		fr.add(bt);
		
		//添加时间监听器的方法
		myEvent();
		
		//使得窗体可见
		fr.setVisible(true);
	}
	
	//创建时间监听器的方法
	private void myEvent()
	{
		//添加窗体的监听器,使得窗体点“×”关闭,使用窗体监听器WindowListener的适配器抽象类WindowAdapter
		fr.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		
		//添加按钮的键盘的监听事件,同样使用KeyListener的适配器——KeyAdapter
		bt.addKeyListener(new KeyAdapter() {
			//void keyPressed(KeyEvent e) 按下某个键时调用此方法。 
			public void keyPressed(KeyEvent e)
			{
				//我们测试同时按下CTRL与Enter的组合键触发事件,使用2个方法
//public boolean isControlDown()返回 Control 修饰符在此事件上是为 down。也就是判断CTRL键是否按下 
// int getKeyCode() 返回与此事件中的键关联的整数 keyCode; char getKeyChar() 返回与此事件中的键关联的字符。
//这两个方法就是答应当前按下的键的String表示以及其在KeyEvent中对应的数字,KeyEvent已经将这些数字封装为常量。
				if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER )
//我们这里同时设置e.getKeyCode() == KeyEvent.VK_ENTER && e.getKeyCode() == KeyEvent.VK_ESCAPE
//想实现组合键的功能是没办法实现的,因为同一时间这句只会监视到一个按键的按下,就是同一时间getKeyCode只能接收一个按键值
//因此我们需要isControlDown这样的方法来实现组合键
					System.out.println("ctrl+enter is run");
							
				//static String getKeyText(int keyCode) 返回描述 keyCode 的 String 
				System.out.println(e.getKeyText(e.getKeyCode())+"---"+e.getKeyCode()+"---"+e.getKeyChar());
/*结果:
Shift---16---?
X---88---x
发现getKeyText返回code所对应的整数的String,可以全部表示;而getKeyChar返回code对应的整数的char(在ASCII表中16对应?,而在KeyEvent中,16对应shift按键)
有一些按键如Shift只能用String表示,char类型接收便显示?
 */
			}
		});				
	}
	public static void main(String[] args) 
	{
		new MouseEventDemo();
	}
}

  我们再做一个键盘事件的监听,针对文本框TextField

package pack;
import java.awt.*;
import java.awt.event.*;//此类中除了监听器就是事件类

public class MouseEventDemo
{
	private Frame fr;
	//TextField 对象是允许编辑单行文本的文本组件。
	private TextField tf;
	
	MouseEventDemo()
	{
		init();
	}
	
	//同样,创建初始化窗口的方法
	public void init()
	{
		fr = new Frame("my frame");
		tf = new TextField(20);//一行文本区域长度设置为20,不会自动换行
		
		//设置窗体
		fr.setBounds(300,100,400,200);
		fr.setLayout(new FlowLayout());
		//将文本区域添加到窗体
		fr.add(tf);
		
		//添加时间监听器的方法
		myEvent();
		
		//使得窗体可见
		fr.setVisible(true);
	}
	
	//创建时间监听器的方法
	private void myEvent()
	{
		//添加窗体的监听器,使得窗体点“×”关闭,使用窗体监听器WindowListener的适配器抽象类WindowAdapter
		fr.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		
	//添加tf的键盘监听器——要求文本框只能键入数字,如果键入的内容不符合,不显示在文本框
		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(e.getKeyText(code)+"键入的值非法!!!");
					//public void consume()使用此事件,以便不会按照默认的方式由产生此事件的源代码来处理此事件。 
					e.consume();//作用是当不满足条件的时候,事件e相对应的动作不会执行。也就是如果打入的是非数字,那么键盘事件调用consume方法,也就不会执行键盘输入的动作,也就是非数字无法显示在文本框
				}
			}
		});
	}
	public static void main(String[] args) 
	{
		new MouseEventDemo();
	}
}

6、练习——对话框Dialog
  注意Dialog与Frame同为顶层窗体!Dialog一般不单独存在,一般和其他窗体一同存在。关于Dialog模式的解释(22-10,3.30)
  练习:列出指定目录内容:

/*
 * 需求:首先,定义一个文本框,在文本框中输入某文件夹的链接
 * 如果成功打开文件夹,就在下面的文本区域显示文件夹中的文件以及文件夹名称
 * 如果文件夹不存在,弹出一个提示框,显示输入的文本错误!
 */
package pack;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class  MyWindowDemo
{
	//首先定义大框Frame的引用——包含一个文本框,一个按钮以及一个文本区域
	private Frame fr;
	private TextField tf;
	private Button bt1;
	private TextArea ta;
	
	//定义弹出对话框Dialog的引用——包含一个标签以及按钮
	private Dialog dl;
	private Label lb;
	private Button bt2;
	
	MyWindowDemo()
	{
		init();
	}
	//初始化函数
	public void init()
	{
		//初始化Frame以及其组件
		fr = new Frame("my frame");
		tf = new TextField(60);//文本框为60行
		bt1 = new Button("转到");
		ta = new TextArea(25,70);//文本区域为25行70列
		//设置Frame的格式
		fr.setBounds(300,100,600,500);
		fr.setLayout(new FlowLayout());
		//将Frame的组件按照流式的模式添加到Frame中
		fr.add(tf);
		fr.add(bt1);
		fr.add(ta);
		
		//初始化Dialog以及其组件——Dialog本身就是一个窗体,不能添加到Frame中,并且其需要设置自己的格式
		//构造一个最初不可见的 Dialog,它带有指定的所有者 Frame、标题和模式。
		//模式设置为——指定在显示的时候阻止用户将内容输入到其他顶级窗口中。
		dl = new Dialog(fr,"提示信息",true);
		lb = new Label();//先不设置label的文本内容,后面工具具体情况设置提示信息
		bt2 = new Button("确定");
		//设置Dialog的格式——注意这一部分也需要设置,否则Dialog无法显示
		dl.setBounds(400,200,240,150);
		dl.setLayout(new FlowLayout());
		//将lb与bt2添加到dl中
		dl.add(lb);
		dl.add(bt2);
		
		//设置监视器方法
		myEvent();
		
		//设置Frame可见
		fr.setVisible(true);
	}
	
	private void myEvent()
	{
		//首先是Frame的关闭功能
		fr.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		//其次是弹出框Dialog的功能,首先是按按钮“确定”会隐藏当前的Dialog框——不会退出程序,只是将其不可见
		bt2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				dl.setVisible(false);//将Dialog框设置不可见
			}
		});
		//其次,关闭Dialog框也会设置Dialog框不可见
		dl.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				dl.setVisible(false);//将Dialog框设置不可见
			}
		});
		//注意,按钮“确定”以及按Dialog窗体的“×”都会使得Dialog的窗体不可见而不会退出所有窗体
		//而使用System.exit(0)会退出所有窗体
		
		//其次,Frame窗体的“转到”按钮,按下后会执行一系列动作
		bt1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				showDir();//调用执行相应动作的方法
			}
		});
		//键盘的Enter键也可以执行相应的动作
		//这里事件源是文本框tf,我们在输入文件路径后,再在文本框中输入按钮“Enter”的值,就触发相应的键盘动作
		//当然这里也可以为按钮“转到”设置同样的功能
		tf.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode() == KeyEvent.VK_ENTER)
					showDir();//调用执行相应动作的方法
			}
		});
		
	}
	//接下来是处理“转到”动作的方法
	private void showDir()
	{
		String dirPath = tf.getText();//首先,用一个String变量接收文本框收到的目录的路径
		File dir = new File(dirPath);//其次,创建目录的File对象
		//如果目录的文件对象存在且是一个文件夹,对其进行遍历
		if(dir.exists() && dir.isDirectory())
		{
			ta.setText("");//这一部分的功能是将前一次遍历文件夹的结果清除
			String[] name = dir.list();//返回dir文件夹下面的文件以及文件夹的名字
			//遍历name
			for(String names : name)
			{
				//setText:将此文本组件显示的文本设置为指定文本。 
				//注意,如果这里使用setText(),那么只能传进一个文件,因为每传进一个文件,这个文件就会将前面的文件覆盖!
				//append(String str)将给定文本追加到文本区的当前文本。因此,使用append就可以!
				ta.append(names+"\r\n");//将当前文件夹或文件的目录添加到文本区域并换行
				//注意,这里换行只能使用“\r\n”,因为是要在文本区域中换行而不是在控制台换行
			}
		}
		else
		{
			String info = "您输入的路径:"+dirPath+"是错误的,请重输";
			//将提示信息添加到Label
			lb.setText(info);
			//注意这种情况下将Dialog框设置为可见
			dl.setVisible(true);
		}
	}
	
	public static void main(String[] args) 
	{
		new MyWindowDemo();
	}
}

7、菜单
  首先注意区分菜单的各个类

MenuBar 类封装绑定到框架的菜单栏的平台概念。为了将该菜单栏与 Frame 对象关联,可以调用该框架的 setMenuBar 方法。
——既通过MenuBar这个菜单平台将菜单绑定到指定框架Frame。
另一方面,MenuBar菜单平台有一个方法:Menu add(Menu m)  将指定的菜单添加到菜单栏。
 ——该方法用于为菜单平台MenuBar添加菜单Menu。
 Menu 对象是从菜单栏部署的下拉式菜单组件。Menu下面有一个方法:MenuItem add(MenuItem mi) 将指定的菜单项添加到此菜单。 
 ——该方法用于添加菜单的菜单项MenuItem(菜单的条目)
 另外,菜单中也可以添加子菜单。

总结:一个菜单,首先需要菜单平台MenuBar,然后创建菜单对象Menu,将菜单Menu的对象添加到MenuBar,而MenuBar则将菜单整体绑定到Frame框架。而菜单Menu既可以添加子菜单,也可以添加菜单条目MenuItem。

  菜单的示例如下:

package pack;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class  MyMenuDemo
{
	//首先定义各类的引用
	private Frame fr;
	private MenuBar mb;//菜单平台
	private Menu me,subMe;//菜单与子菜单
	private MenuItem closeMi,subMi;//条目与子条目
	
	MyMenuDemo()
	{
		init();
	}
	
	private void init()
	{
		//初始化框架
		fr = new Frame("my frame");
		fr.setBounds(300,100,500,600);
		fr.setLayout(new FlowLayout());
		
		//首先创建平台对象
		mb = new MenuBar();
		//其次创建菜单对象
		me = new Menu("菜单");
		subMe = new Menu("子菜单");
		//最后是菜单条目
		closeMi = new MenuItem("退出");
		subMi = new MenuItem("子条目");
		
		//接着从下到上添加,先是子菜单添加子条目
		subMe.add(subMi);
		//其次是菜单添加子菜单与条目
		me.add(subMe);
		me.add(closeMi);
		//最后是菜单平台添加菜单
		mb.add(me);
		
		//使用Frame的setMenuBar()添加菜单平台
		fr.setMenuBar(mb);
		
		//添加事件
		myEvent();
		fr.setVisible(true);
		
	}
	
	private void myEvent()
	{
		//窗口关闭
		fr.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		
		//菜单条目添加事件
		closeMi.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
	}
	
	
	public static void main(String[] args) 
	{
		new MyMenuDemo();
	}
}

  菜单相关练习:

package pack;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class MyMenuTest
{
	//首先,定义各类的引用
	private Frame fr;
	//菜单各类
	private MenuBar mb;
	private Menu fileMenu;
	private MenuItem saveItem , closeItem , openItem;	
	//文本区域用于显示读取的文件内容
	private TextArea ta;	
	//文件对话框
	private FileDialog openDia , saveDia;	
	//文件对象
	private File file;
	
	MyMenuTest()
	{
		init();
	}
	
	private void init()
	{
		//首先是窗体的初始化
		fr = new Frame("my frame");
		fr.setBounds(300,100,650,600);
//		fr.setLayout(new FlowLayout());这里为了窗体更加好看,我们默认使用边界布局
		ta = new TextArea();//初始化文本区域,但是不知道行列数目
		
		//接下来是菜单初始化
		mb = new MenuBar();
		fileMenu = new Menu("文件");
		saveItem = new MenuItem("保存");
		openItem = new MenuItem("打开");
		closeItem = new MenuItem("关闭");
		//将菜单添加到Frame
		fileMenu.add(saveItem);
		fileMenu.add(openItem);
		fileMenu.add(closeItem);
		mb.add(fileMenu);
		fr.setMenuBar(mb);
		
		//初始化文件对话框——指定文件对话框所对应的窗体,名称以及其模式
		openDia = new FileDialog(fr,"打开文件",FileDialog.LOAD);//模式为查找读取文件
		saveDia = new FileDialog(fr,"保存文件",FileDialog.SAVE);//模式为保存文件
		
		//加载事件
		myEvent();
		
		fr.add(ta);//注意将文本区域添加进来
		fr.setVisible(true);
	}
	
	private void myEvent()
	{
		//首先是窗体的关闭
		fr.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);	
			}
		});
		//菜单关闭条目的事件——关闭窗体
		closeItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
		
		//菜单保存条目事件——将文本区域的内容保存到相应的文件中
		saveItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
//这里为什么要判断文件是否存在?——我们只有在文件不存在的时候才需要获取文件的路径与名称并创建相应File对象,以方便接下来将内容写入文件。
//如果文件存在,我们直接将内容写入该文件即可,不需要再获取文件路径名称与相应对象。
//比如,我们初始创建一个文件并输入相应内容,那么这个文件保存之前不存在,我们按“保存”按钮,就需要获取文件的路径与名称并创建相应File对象,才能保存文件
//如果文件之前就存在,我们按“保存”按钮,不需要创建新的File对象,而是在之前文件的基础上直接将新的内容写入即可(见22-13解析)
//在这里就是我们在文本框中输入内容并保存到一个文件,第一次File对象不存在会弹出FileDialog,
//而我们修改内容,再次保存,就不会弹出FileDialog,因为上一次保存的时候file文件对象已经存在,只会将新内容写入原来的file
//如果想存到其他文件,需要有“另存为”的功能
				if(file == null)
				{
					//首先将保存文件对话框设置可见
					saveDia.setVisible(true);
					//保存的时候我们会设置保存的目录与保存的文件的名称,我们先获取这个路径与名称
					String dirPath = saveDia.getDirectory();//获取文件保存的目录,既获取此文件对话框的目录
					String fileName = saveDia.getFile();//获取保存的文件的名称
					//如果文件保存路径或者文件名称为空,说明我们没有选择或者选择错误,退出此方法
					if(dirPath==null || fileName==null)
						return ;
					//如果文件保存路径与文件名存在,我们创建相应的File对象
					file = new File(dirPath,fileName);
				}
				//接下来将文本区域内容写入文件
				BufferedWriter bufw = null;
				try 
				{
					bufw = new BufferedWriter(new FileWriter(file));
					String text = ta.getText();//获取文本区域的内容
					//由于getText会获取文本区域的所有文本,因此这里只需要写一次
					bufw.write(text);//将text写入相应文件
					bufw.flush();
				}
				catch(IOException e1)
				{
					throw new RuntimeException("保存失败");
				}
				finally
				{
					try
					{
						if(bufw != null)
							bufw.close();
					}
					catch(IOException e2)
					{
						throw new RuntimeException("写入关闭失败"); 
					}
				}
			}
		});
		
		//菜单打开条目的事件——将打开的文件的内容读取到文本区域中
		openItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				//首先将打开文件对话框设置可见
				openDia.setVisible(true);	
				
				//打开的时候,我们要为打开设置打开文件后文件数据存放的位置——见22-12,8.20解析
				//我们在打开的时候会指定相应的文件路径以及文件,获取文件路径以及文件名——见22-12,10.40解析
				//通过FileDialog的对象来获取要操作的文件路径以及文件名称
				String dirPath = openDia.getDirectory();
				String fileName = openDia.getFile();
//				System.out.println(dirPath+"..."+fileName);
				//接下来同样判断文件路径与文件名是否为空,为空退出函数——为什么要有这部分代码,见22-12,13.35解析
				//我们在打开的时候如果点击取消,既有文件路径但是没有选择文件,没有文件名,这个时候下面的代码还在使用文件名,就会出现空指针异常
				//因此,我们在使用文件名以及文件路径之前需要判断文件名以及文件路径是否存在,不存在便退出函数
				if(dirPath==null || fileName==null)
					return ;
				//如果文件保存路径与文件名存在,我们创建相应的File对象
				file = new File(dirPath,fileName);
				//在写入文件内容之前,需要将文本区域之前的内容清空
				ta.setText("");
				
				BufferedReader bufr = null;
				try
				{
					bufr = new BufferedReader(new FileReader(file));
					//由于文件内容较多,需要一行一行写入文本区域
					String line = null;
					while((line = bufr.readLine()) != null)
					{
						//注意,文本区域在添加的时候,要使用append,这样才会使得后面的内容不会覆盖前面的内容
						ta.append(line+"\r\n");
					}
				}
				catch(IOException e1)
				{
					throw new RuntimeException("打开失败");
				}
				finally
				{
					try
					{
						if(bufr != null)
							bufr.close();
					}
					catch(IOException e2)
					{
						throw new RuntimeException("读取关闭失败"); 
					}
				}
			}
		});
	}
	
	public static void main(String[] args) 
	{
		new MyMenuTest();
	}
}

8、jar包的双击执行功能
(参考——黑马毕向东Java课程笔记(day10-7——10-10):面向对象(第七部分)包(package)——中关于jar包使用的介绍)
  由于我们使用了匿名内部类,因此使用eclipse编译之后在“F:\研究生学习资料\java\eclipse\eclipse\workspace\Test\bin\pack”文件夹下面出现了很多个类,如下图:
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第7张图片
  我们使用jar包将这些类封装起来,下面我们先使用cmd命令行来示范一下。
  我首先,我们在“G:\project”路径下创建一个“MyMenuTest.java”文件,这些代码会存放到“mymenu”包中,使用cmd命令行进行编译,将生成的包含“MyMenuTest.class”文件的“mymenu”包放到当前路径下:
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第8张图片
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第9张图片
  结果生成了相应的包与“.class”文件,我们将这个“mymenu”包封装为jar包,因为包就在当前路径“G:\project”下,我们不需要切换文件或者设置classpath,直接将这个包打包即可:
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第10张图片
  发现在当前路径下生成了一个mymenu的jar包,现在我们是想实现双击这个jar包就可以运行的功能,但是jar包中有很多个类,不知道要执行哪一个(参考22-14,3.00处解析)。
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第11张图片
  我们必须把包含主函数的类告诉jar包,这样双击的时候jar才知道执行哪一个。我们要在jar包的配置信息文件“MANIFEST.MF”中添加主类的名称信息,但是这个文件我们不能直接修改,我们想添加相应的主类名称的配置信息,就必须先将想配置的信息先写到一个“confi_infor.txt”文件中:(注意写类的时候带上包名,最后要回车,“:”号之后要带一个空格,这是标准格式)
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第12张图片
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第13张图片
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第14张图片
  我们发现生成了“my.jar”文件,并且双击可以运行,而且相应的配置文件中有主函数的配置信息!
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第15张图片
黑马毕向东Java课程笔记(day22-01——22-14):GUI:Frame窗口创建、Button、鼠标事件、监听器、对话框、菜单、生成可执行的jar包(cmd与eclipse))_第16张图片
  其实这里还需要做一步动作,既jar文件必须要在本地注册过才可以使用。其实jar文件在我们安装JDK的时候就已经注册过了,如果我们仅仅是将把JDK的目录拷贝到某一台没有安装JDK的电脑时使用的时候,就必须配置。视频中介绍的是winxp系统下的处理方法,我们在win10与win7系统下的处理方式如下链接
win10下jar注册处理方式

  至于如何在eclipse中生成可执行的jar文件,见如下链接文章:
在eclipse到处可执行的jar文件
jar:JavaTM archive file

你可能感兴趣的:(Java资料)