Java的基本学习(五)——高级UI设计与异常处理

前言:

我们继续接着前面的内容来继续学习

 

 

 

 


高级GUI组件设计

Java采用委托事件模型来处理事件。当事件产生时,通过注册的监听器对象的Listener接口的事件处理方法来进行处理。然而,当一个Listener接口有多个处理方法(例如:鼠标事件有按下鼠标按钮、释放鼠标按键、单机鼠标按键)时,则不管是否需要,必须实现所有方法,这样下去会造成资源的浪费,并使系统开销加大。为了解决此类问题,Java语言为这些Listener接口提供了适配器类(Adapter),事件适配器(EventAdapter)为我们提供了一种简单的处理手段。当事件源注册了含有多个处理方法的监听器对象时,可以通过继承事件所对应的Adapter类,重写所需要的方法,而不需要的方法则不用重写,这样就可以缩短程序代码的编写。

KeyEvent事件及其响应:

KeyEvent事件

能触发KeyEvent事件的动作是键盘操作,所以简称为键盘操作。KeyEvent事件有三种:两个低级事件(按下(Pressed)和释放键(Released))和一个高级事件(键按下并释放(按键被敲击,Typed))。

键盘事件的响应

package 测试;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class test extends JApplet
{
	String s,s1;
	JLabel lb1=new JLabel("请按键盘");
	JLabel lb2=new JLabel("复制结果");
	//用来输入文字
	JTextField tf1=new JTextField(10);
	//用来显示文件内容
	JTextArea tf2=new JTextArea(5,10);
	Container cp=getContentPane();
	FlowLayout flow=new FlowLayout(FlowLayout.CENTER,5,5);
	public void init()
	{
		cp.setLayout(flow);
		cp.add(lb1);
		cp.add(tf1);
		cp.add(lb2);
		cp.add(tf2);
		tf1.addKeyListener(new koLis());
	}
	//继承了一个事件适配器的类,对应的监听器是KeyListener
	//这里是一个Java嵌套类
	class koLis extends KeyAdapter
	{
		//只要有键入就会触发
		public void keyTyped(KeyEvent e)
		{
			//获取文本框的内容及键入的字符
			s=tf1.getText()+e.getKeyChar();
			//若按回车键,则将文本框的内容送入文本域
			if(e.getKeyChar()=='\n')
			{
				//文本域中已经有的文字再加上新的
				s1=tf2.getText()+s;
				tf1.setText("");
				tf2.setText(s1);
			}
		}
	}
}

MouseEvent事件及其响应

MouseEvent事件是低级事件,在任何组件上都可以触发该事件。组件上触发MouseEvent事件的动作是鼠标操作。MouseEvent事件分为两类:

  • 使用MouseListener接口处理的鼠标事件。awt.Event类的MouseListener接口能够监听的5种鼠标事件是:按下鼠标按键、释放鼠标按键、单机鼠标按键(按下并释放)、鼠标光标进入或离开组件几何形状的未遮掩部分
  • 使用MouseMotionListener接口处理的鼠标移动事件。awt.Event类的MouseMotionListener接口能够监听的两种鼠标移动的事件是:移动鼠标和拖动鼠标事件
package 测试;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class test extends JApplet
{
	int x,y;
	JLabel lb1=new JLabel("X:"),lb2=new JLabel("Y:"),lb3=new JLabel("");
	JTextField tf1=new JTextField(5),tf2=new JTextField(5);
	Container cp=getContentPane();
	FlowLayout flow=new FlowLayout(FlowLayout.CENTER,5,5);
	public void init()
	{
		cp.setLayout(flow);
		cp.add(lb1);
		cp.add(tf1);
		cp.add(lb2);
		cp.add(tf2);
		cp.add(lb3);
		addMouseListener(new mouseListener());
		addMouseMotionListener(new koLis());
	}
	//此适配器类监听鼠标各种信息情况
	class mouseListener extends MouseAdapter
	{
		public void mouseClicked(MouseEvent e)
		{ 
			lb3.setText("点击鼠标");
		}
		public void mousePressed(MouseEvent e)
		{
			lb3.setText("鼠标按钮按下");
		}
		public void mouseExited(MouseEvent e)
		{
			lb3.setText("鼠标不在窗口");
		}
		public void mouseReleased(MouseEvent e)
		{
			lb3.setText("鼠标按钮松开");
		}
	}
	//此监听器监听移动情况
	class koLis implements MouseMotionListener
	{
		public void mouseMoved(MouseEvent e)
		{
			x=e.getX();
			y=e.getY();
			tf1.setText(String.valueOf(x));
			tf2.setText(String.valueOf(y));
		}
		public void mouseDragged(MouseEvent e)
		{
			lb3.setText("拖动鼠标");
		}
	}
}

WindowsEvent事件及其响应

在JFrame容器上,如果用户打开或关闭容器,则可以触发WindowEvent事件。 WindwoEvent事件是低级事件,可以设计打开、关闭、激活、停用、图标化或取消图标化JFrame容器的操作来产生WindowEvent事件。

package 测试;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class test 
{
	JLabel lb1=new JLabel("这是第一个窗口");
	JLabel lb2=new JLabel("这是第二个窗口");
	public static void main(String [] arg)
	{
	   	test t=new test();
	}
	public test()
	{
		//创建JFrame对象
		JFrame f1=new JFrame();
		JFrame f2=new JFrame();
		//创建JFrame的容器对象,获得ContentPane
		Container cp=f1.getContentPane();
		Container cp1=f2.getContentPane();
		f1.setTitle("JFrame1");
		f2.setTitle("JFrame2");
		f1.setSize(150,100);
		f2.setSize(150,100);
		cp.add(lb1);
		//设置窗口可见
		f1.setVisible(true);
		cp1.add(lb2);
		f2.setVisible(true);
		f1.addWindowListener(new WinLis());
		f2.addWindowListener(new WinLis());		
	}
	//Window事件适配器
	class WinLis extends WindowAdapter
	{
		//打开窗口
		public void windowOpen(WindowEvent e)
		{
		}
		//设置窗口成为活动窗口
		public void windowActivated(WindowEvent e)
		{
		}
		//设置窗口成为非活动窗口
		public void windowDeactivated(WindowEvent e)
		{
		}
		//窗口关闭
		public void windowClosing(WindowEvent e)
		{
			System.exit(0);
		}
		//最小化窗口
		public void windowIconified(WindowEvent e)
		{
		}
	}
}

 

JScrollPane与JScrollBar组件:

JScollPane:

当窗口的内容大于窗口时,可以在窗口的右边和下边设置滚动条,借助于滚动条就可以看到整个窗口的内容。JScrollPane就是具有这种功能的组件,我们将它成为滚动窗面板,用于滚动窗口。

JScrollBar组件:

JScrollPane是由JViewPort和JScrollBar组件组成的。JViewPort组件主要是负责显示内容的区域大小;JScrollBar组件则产生窗口滚动条,让用户看到整个内容。用户使用JScrollPane组件时不会直接与JViewPort和JScrollBar组件接触,使用比较方便。但是,当想对滚动条做更细的设置时(例如,在拖动时一次滚动多少区域等),就必须了解JScrollBar所提供的功能。

AdjustmentEvent事件应用举例:

JScrollBar对象接收AdjustmentEvent事件。

示例:

package 测试;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class test 
{
	int r=0,g=0,b=0;
	String s,s1=" ",s2=" ",s3=" ";
	//声明建立滚动条的变量
	JScrollBar sbr,sbg,sbb;
	JLabel lb1=new JLabel("刻度:"),lb2=new JLabel(" 标签:"),lb3=new JLabel("  调色板  "),
			lbr=new JLabel("红色"),lbg=new JLabel("绿色"),lbb=new JLabel("蓝色");
	public test()
	{
		JFrame f=new JFrame("JScrollBar");
		Container cp=f.getContentPane();
		Box baseBox=Box.createHorizontalBox();
		cp.add(baseBox);
		//创建box1
		Box box1=Box.createHorizontalBox();
		//给box1加两个标签
		box1.add(lb1); 
		box1.add(lb2);
		//加box1加到baseBox中
		baseBox.add(box1);
		//创建box3
		Box box3=Box.createVerticalBox();
		//将box3加入到baseBox中
		baseBox.add(box3);
		//设置标签颜色
		lb3.setBackground(new Color(0,0,0));
		//设置标签边框
		lb3.setBorder(BorderFactory.createEtchedBorder());
	    //让组件变得不透明,使标签颜色显示出来
		lb3.setOpaque(true);
		lb3.setMaximumSize(new Dimension(450,200));
		box3.add(lb3);
		
		//sbr滚动条的设置
		//创建水平方向滚动条对象
		sbr=new JScrollBar(JScrollBar.HORIZONTAL,10,10,0,260);
		//设置此滚动条拖动滚动块时的单位向量
		sbr.setUnitIncrement(5);
		//设置鼠标在滚动条上点击时滚动块的块增量
		sbr.setBlockIncrement(10);
		//注册监听器对象
		sbr.addAdjustmentListener(new Dj());
		//给box3添加滚动条和对应标签
		box3.add(lbr);
		box3.add(sbr);
		
		//sbg滚动条的设置
		sbg=new JScrollBar(JScrollBar.HORIZONTAL,10,10,0,260);
		sbg.setUnitIncrement(5);
		sbg.setBlockIncrement(10);
		sbg.addAdjustmentListener(new Dj());
		box3.add(lbg);
		box3.add(sbg);
		
		//sbb滚动条的设置
		sbb=new JScrollBar(JScrollBar.HORIZONTAL,10,10,0,260);
		sbb.setUnitIncrement(5);
		sbb.setBlockIncrement(10);
		sbb.addAdjustmentListener(new Dj());
		box3.add(lbb);
		box3.add(sbb);
		
		f.pack();
		f.setVisible(true);
		f.addWindowListener(new WinLis());
	}
	
	class WinLis extends WindowAdapter
	{
		public void windowClosing(WindowEvent e) {
			System.exit(0);
		}
	}
	class Dj implements AdjustmentListener
	{

		@Override
		public void adjustmentValueChanged(AdjustmentEvent e) {
			if((JScrollBar)e.getSource()==sbr)
			{
				r=e.getValue();
				s1="red";
			}
			if((JScrollBar)e.getSource()==sbg)
			{
				g=e.getValue();
				s2="green";
			}
			if((JScrollBar)e.getSource()==sbb)
			{
				b=e.getValue();
				s3="blue";
			}
			s=s1+r+" "+s2+g+" "+s3+b;
			lb2.setText(s);
			lb3.setBackground(new Color(r,g,b));
		}
		
	}
	public static void main(String[] arg)
	{
		test t=new test();
	}
}

JTabbedPane容器:

当界面上需要放置的组件很多时,可以使用的另一个容器是JTabbedPane。JTabbedPane容器与我们日常使用的卡片盒相似,它由多个称为标签框架的卡片和表明该框架的标签组成。每个标签框架和标签都自成一个系统(也可以称为一张卡片),我们可以在标签框架中加入各式各样的组件和功能。由于这些卡片被叠放在一起,为了使用方便,卡片上的标签在顶行或底部排成一行(也可以在左边或右边排成一列),当用鼠标点击某一个标签时,这个标签所在的卡片(标签框窗口)就会被翻到最上面,显示出此框架的内容

示例:

package 测试;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class test extends JFrame
{
	//创建JTabblePane对象,并指定标签显示在上方
	JTabbedPane jtab=new JTabbedPane(JTabbedPane.TOP);
	//声明JScrollPane的引用变量
	JScrollPane sp;
	public static void main(String args[])
	{
		test f=new test();
		f.setTitle("JTabbedPane对象的应用");
		f.setSize(300,300);
		f.setVisible(true);
	}
	public test()
	{
		//声明标签的数组
		JLabel lb[]=new JLabel[6];
		//声明图片对象的引用变量
		Icon pic;
		//声明标签名称对象的引用变量
		String title;
		String p;
		for(int i=1;i<=5;i++)
		{
			p="/image/"+"00"+i+".jpg";
			//获取图片
			pic=new ImageIcon(getClass().getResource(p));
			//创建JLabel对象
			lb[i]=new JLabel();
			//设定JLabel图标
			lb[i].setIcon(pic);
			//设定标签名称
			title="第 "+String.valueOf(i)+" 页";
			//将JLabel对象加入jtab的对象中
			jtab.add(title,lb[i]);
		}
		//将jtab对象加入到窗口中
		getContentPane().add(jtab);
		int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
		int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
		//创建JScrollPane对象,并加载jtab对象
		sp=new JScrollPane(jtab,v,h);
		getContentPane().add(sp);
		//注册监听器
		addWindowListener(new WinLis());
	}
	class WinLis extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			System.exit(0);
		}
	}
}

菜单设计:

菜单和工具可提供简单明了的指示说明,使用户顺利地完成软件的操作。菜单是非常重要的GUI组件,是软件中必备的组件之一,Java语言提供了多种多样的菜单,如一般式、复选框式、快捷键式及弹出框式等,这里仅介绍一般式菜单。

在Java中一个一般式菜单由菜单栏(JMenuBar)、菜单(JMenu)和菜单项(JMenuItem)三类对象组成。

菜单栏

菜单栏(JMenuBar)用来封装与菜单相关的各项操作,它只是用来管理菜单,不参与交互式操作。Java应用程序中的菜单都包含在一个菜单栏对象之中,

菜单

菜单(JMenu)是用来存放和整合菜单项(JMenuItem)的组件,它是构成一个菜单栏不可或缺的组件之一。菜单可以是单一层次的结构,也可以是一个多层次的结构,具体使用何种形式的结构取决于界面设计的需要。

菜单项

菜单项(JMenuItem)是用来封装与菜单项相关的操作,它是菜单系统中最基本的组件。

 

接下来我们来看个制作菜单的示例:

package 测试;
import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.event.*;
public class test extends JFrame
{
	JTextArea tf=new JTextArea();
	//创建JMenuBar对象
	JMenuBar bar=new JMenuBar();
	//创建JMenu对象
	JMenu menu=new JMenu("文件");
	//创建JMenuItem对象
	JMenuItem newf=new JMenuItem("新建");
	JMenuItem open=new JMenuItem("打开");
	JMenuItem close=new JMenuItem("关闭");
	JMenuItem quit=new JMenuItem("退出");
	public test()
	{
		
		//设定JFrame的标签
		//这里是手动给父类的构造函数传了个参数
		//一般子类创建对象都会调用父类的无参构造函数
		super("test");
		//创建JFrame的容器对象
		getContentPane().add(new JScrollPane(tf));
		//设置文本区域为不可编辑
		tf.setEditable(false);
		//设置bar为不透明,若设置bar为透明,则在选择菜单时会有残影存留在JMenuBar上
		bar.setOpaque(true);
		//加入bar到JFrame上
		setJMenuBar(bar);
		//加入JMenuItem对象到menu上
		menu.add(newf);
		menu.add(open);
		menu.add(close);
		//在JMenu中加入一条分割线
		menu.addSeparator();
		menu.add(quit);
		//将menu加载到bar上
		bar.add(menu);
		//注册监听器
		newf.addActionListener(new Ac());
		open.addActionListener(new Ac());
		close.addActionListener(new Ac());
		quit.addActionListener(new Ac());
		addWindowListener(new WinLis());
	}
	class Ac implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			if(e.getSource()==newf)  tf.setText("新建");
			if(e.getSource()==open)  tf.setText("打开");
			if(e.getSource()==close)  tf.setText("关闭");
			if(e.getSource()==quit)  System.exit(0);
		}
	}
	class WinLis extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			System.exit(0);
		}

	}
	public static void main(String[] args)
	{
		JFrame f=new test();
		f.setSize(400,200);
		//设置窗口可见
		f.setVisible(true);
	}	
}

对话框设计

对话框(Dialog),也就类似于c++那边的messagebox,是一种特殊的窗体,通过一个或多个组件与用户交互。

与JFrame一样,对话框有边缘、有标题且独立存在的容器,并且不能被其他容器所包容,但是对话框不能作为程序的最外层容器,也不能包含菜单条,此外,Java的对话框上没有最大化和最小化按钮。

Java提供了 JDialog 和 JOptionPane 两类对话框组件。

JOptionPane

JOptionPane提供了许多现成的对话框样式,用户只需使用该类提供的静态方法,指定方法中所需要的参数,JOptionPane对话框就能轻易地显示出来。

可将JOptionPane类的对话框分为4种类型,分别只是给出提示信息的Message Dialog、要求用户进行确认的Confirm Dialog、可输入数据的Input Dialog、和由用户自己定义类型的Option Dialog。

示例展示Message Dialog:

package 测试;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test implements ActionListener
{
	JFrame f=null;
	public test()
	{
		f=new JFrame("OptionPane Demo");
		Container cp=f.getContentPane();
		cp.setLayout(new GridLayout(2,2));
		JButton bt=new JButton("Show Error Icon");
		bt.addActionListener(this);
		cp.add(bt);
		bt=new JButton("Show Warning Icon");
		bt.addActionListener(this);
		cp.add(bt);
		bt=new JButton("Show Plain Icon");
		bt.addActionListener(this);
		cp.add(bt);
		bt=new JButton("Show User Define Icon");
		bt.addActionListener(this);
		cp.add(bt);
		//调整此窗口的大小
		f.pack();
		//可视
		f.setVisible(true);
		f.addWindowListener(new WinLis());
	}
	class WinLis extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			System.exit(0);
		}
	}
	public static void main(String []args) {
		new test();
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd=e.getActionCommand();
		//对话框标题名
		String title="Message Dialog";
		String message="";
		//指定信息类型
		int type=JOptionPane.PLAIN_MESSAGE;
		if(cmd.equals("Show Error Icon")) {
			type=JOptionPane.ERROR_MESSAGE;
			message="Error Message";
		}else if(cmd.equals("Show Warning Icon")) {
			type=JOptionPane.WARNING_MESSAGE;
			message="Warning Message";
		}else if(cmd.equals("Show Plain Icon")) {
			type=JOptionPane.PLAIN_MESSAGE;
			message="Plain Message";
		}else if(cmd.equals("Show User Define Icon")) {
			type=JOptionPane.PLAIN_MESSAGE;
			//输出设置图标的信息对话框
			JOptionPane.showMessageDialog(f, message,title,type,new ImageIcon("/image/001.jpg"));
			return;
		}
		//输出未设图标的信息对话框
		JOptionPane.showMessageDialog(f, message,title,type);
	}
}

实现可输入的对话框(Input Dialog):

package 测试;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test implements ActionListener
{
	JFrame f=null;
	JLabel lb=null;
	public test()
	{
		f=new JFrame("OptionPane Demo");
		Container cp=f.getContentPane();
		//面板
		JPanel pa=new JPanel();
		pa.setLayout(new GridLayout(2,1));
		//给Panel加入两个按钮
		JButton bt=new JButton("Show Text Input");
		bt.addActionListener(this);
		pa.add(bt);
		bt=new JButton("Show ComboBox Input");
		bt.addActionListener(this);
		pa.add(bt);
		lb=new JLabel("",JLabel.CENTER);
		//在JFrame容器中,上面加上标签(标签很窄),下面加上Panel面板
	    cp.add(lb,BorderLayout.NORTH);
	    cp.add(pa,BorderLayout.CENTER);
		
		f.pack();
		f.setVisible(true);
		f.addWindowListener(new WinLis());
	}
	class WinLis extends WindowAdapter{
		public void WindowClosing(WindowEvent e) {
			System.exit(0);
		}
	}
	public static void main(String[] arge) {
		new test();
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd=e.getActionCommand();
		String title="Input Dialog";
		String message="您最喜欢哪一种编程语言";
		int messageType=JOptionPane.QUESTION_MESSAGE;
		String[] values= {"VB","C++","JAVA","ASP"};
		String result="";
		if(cmd.equals("Show Text Input")) {
			result=JOptionPane.showInputDialog(f,message,title,messageType);
		}else if(cmd.equals("Show ComboBox Input")) {
			result=(String)JOptionPane.showInputDialog(f,message,title,
					       messageType,null,values,values[0]);
		}
		if(result==null)
			lb.setText("您取消了对话框");
		else
			lb.setText("您输入:"+result);
	}	
}

JDialog对话框

如果JOptionPane提供的样式无法满足我们的需求,就需要使用JDialog来自行设计对话框。用JDialog来制作对话框时,必须制作对话框中的每一个组件,所以比较麻烦。但是,当我们想要了解对话框的更多细节时,还是有必要学习用JDialog来制作对话框的过程的。事实上,当使用JOptionPane时,系统会自动产生JDialog组件,并将JOptionPane的内容放入JDialog的ContentPane中,而不需要我们介入。

需要说一下的是,在JDialog的初始方法中有一个这样的构造方法:

JDialog(Frame owner,String title,boolean modal)

表中的modal是对话框的操作模式,可分为模态和非模态两种,用modal参数的true与false表示。当modal为true,则称为模态对话框,它要求用户在应用程序继续执行之前必须对该对话框进行响应,关闭对话框后才能回到原来的应用程序继续执行。当false时,则称为非模态对话框,非模态对话框则无上述要求。

使用JDialog与JFrame非常类似,要加入组件到JDialog上必须先取得JDialog的ContentPane,然后再把组件加到此ContentPane中

示例:

package 测试;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class test implements ActionListener
{
	String s1=" ";
	JFrame f=null;
	JLabel lb=new JLabel("对话框示例:");
	//声明对话框中的文本框引用变量
	JTextField tf1,tf2;
	//声明对话框引用变量
	JDialog dialog;
	public test()
	{
		f=new JFrame("对话框示例");
		Container cp=f.getContentPane();
		JPanel pa=new JPanel(new GridLayout(3,1));
		pa.add(lb);
		JButton bt=new JButton("进入对话框");
		bt.addActionListener(this);
		pa.add(bt);
		bt=new JButton("结束");
		bt.addActionListener(this);
		pa.add(bt);
		pa.setBorder(BorderFactory.createTitledBorder(
				BorderFactory.createLineBorder(Color.blue,3),
				"对话框示例",TitledBorder.CENTER,TitledBorder.TOP));
		cp.add(pa,BorderLayout.CENTER);
		
		f.pack();
		f.setVisible(true);
		f.addWindowListener(new WinLis());
	}
	class WinLis extends WindowAdapter{
		public void WindowClosing(WindowEvent e) {
			System.exit(0);
		}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd=e.getActionCommand();
		if(cmd.equals("进入对话框")) {
			//在该方法中创建对话框
			dial();
		}else if(cmd.equals("结束")) {
			System.exit(0);
		}
		//对话框中的按钮事件
		if(cmd.equals("确定")) {
			
		}else if(cmd.equals("返回")) {
			s1=tf1.getText();
			s1=s1+tf2.getText();
			lb.setText(s1);
			dialog.dispose();
		}
	}
	public static void main(String[] args) {
		new test();
	}
	public void dial() {
		//创建对话框对象(模态)
		dialog=new JDialog(f,"进入对话框",true);
		//创建对话框的容器对象
		Container diacp=dialog.getContentPane();
		//设置所创建对话框的容器的布局
		JLabel lb1=new JLabel("输入学号:");
		JLabel lb2=new JLabel("输入姓名:");
		//面板布局为3行2列
		JPanel pa1=new JPanel(new GridLayout(3,2));
		tf1=new JTextField(8);
		tf2=new JTextField(8);
		pa1.add(lb1);
		pa1.add(tf1);
		pa1.add(lb2);
		pa1.add(tf2);
		JButton bt1=new JButton("确定");
		pa1.add(bt1);
		bt1=new JButton("返回");
		bt1.addActionListener(this);
		pa1.add(bt1);
		//对话框的容器放入上述面板
		diacp.add(pa1);
		//设置对话框的容器的大小
		dialog.setBounds(150,150,200,150);
		//将对话框变为可见
		dialog.setVisible(true);
	}	
}

 

 


小插曲:

截止这里终于把Java的UI设计记录完了,后面就是学习多线程、网络、数据库了

 


异常处理

异常处理机制

Java的异常处理机制用于及时有效地处理程序运行中的异常情况,Java引入了异常和异常类,并且定义了很多异常类,每个异常类代表一类运行错误,类中包含了该运行错误的信息和处理错误的方法等内容。每当Java程序运行过程中发生一个可识别的运行错误时,系统都会产生一个相应异常类的对象,并由系统中相应的机制来处理,以确保不会产生死机、死循环或其他对操作系统有损害的结果,从而保证了整个程序运行的安全性。

在Java程序中,当程序运行过程中发生异常时,可采用两种方法来处理:

  • 程序被终止并显示一些错误信息给用户
  • 使用Java语言提供的 try-catch-finally 语句自行处理异常

第二种方法的优点很多,其中最主要的优点是将处理异常的代码与程序代码的主线分离开,增强了程序的可读性;其次是可减少中途终止程序运行的可能性。

我们来看一个程序自动抛出异常

package 测试;
public class test{
	public static void main(String[] args) {
		int a,b,c;
		a=67;
		b=0;
		c=a/b;
		System.out.println(a+"/"+b+"="+c);
	}
}

终端输出:

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at 测试.test.main(test.java:7)

异常类的继承:

在Java语言中所有的异常类都继承自java.lang.Throwable类。Throwable类有两个直接子类:一个是Error子类,它包含Java系统或执行环境中所发生的异常,这些异常是用户无法捕捉到的;另一个是Exception类,它包含了一般性的异常,例如I/O异常、SQL异常,这些异常是用户可以捕捉到的(我们的try-catch就是要抓这一类的异常),可以通过产生它的子类来创建自己的异常处理

系统定义的运行异常Error类中,除AWTError类在java.awt包中外,其余的全部在java.lang包中

异常处理语句:

try-catch-finally语句

结构如下

        try {
		//可能发生异常的语句
		statements   
	}
	catch(ExceptionType1 ExceptionObject) {
		//处理异常的程序代码1
		Exception Handing  
	}
	catch(ExceptionType2 ExceptionObject) {
		//处理异常的程序代码2
		Exception Handing  
	}
	.
	.
	.
	finally {
		//无论是否发生异常都要执行的程序代码
		Finally Handing
	}

我们接下来来看一个示例:

package 测试;
public class test{
	public static void main(String args[]) {
		int a,b,c;
		a=67;
		b=0;
		try {
			int x[]=new int[-5];
			c=a/b;
			System.out.println(a+"/"+b+"="+c);
		}
		catch(NegativeArraySizeException e) {
			System.out.println("异常:"+e.getMessage());
			//在命令行打印异常信息在程序中出错的位置及原因
			e.printStackTrace();
		}
		catch(ArithmeticException e) {
			System.out.println("b=0:"+e.getMessage());
		}
		finally {
			System.out.println("End");
		}
	}
}

输出:

异常:null
java.lang.NegativeArraySizeException
End
	at 测试.test.main(test.java:8)

printStackTrace的输出是有可能混乱的,原因如下:

printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不同的输出流,那么在打印时自然就形成了交叉。还有就是输出流是有缓冲区的,所以对于什么时候具体输出也形成了随机。

我们再来看一个嵌套异常的示例:

package 测试;
public class test{
	static int a,b,c;
	public static void main(String args[]) {
		try {
			a=10;
			b=0;
			try {
				c=a/b;
				System.out.println("a/b="+c);
			}
                        //但是改程序其实并没有这个异常
			catch(IndexOutOfBoundsException E) {
				System.out.println("捕捉超出索引异常……");
			}
			finally {
				System.out.println("嵌套内层的finally区块");
			}
		}
		catch(ArithmeticException E) {
			System.out.println("捕捉数学运算异常,b="+b);
		}
		finally {
			System.out.println("嵌套外层的finally区块");
			if(b==0) {
				System.out.println("程序执行发生异常!");
			}
			else {
				System.out.println("程序正常执行完毕");
			}
		}
	}
}

输出:

嵌套内层的finally区块
捕捉数学运算异常,b=0
嵌套外层的finally区块
程序执行发生异常!

抛出异常的throw与throws语句

throw

package 测试;
public class test{
	public static void main(String[] args) {
		try {
			throw new NullPointerException("自编异常");
		}
		catch(NullPointerException e) {
			System.out.println("异常:"+e);
		}
	}
}
异常:java.lang.NullPointerException: 自编异常

throws

在有些情况下,不需要一个方法本身来处理异常,而是希望把异常向上移交给调用这个方法的方法来处理,此时,就可以用throws语句。

throws的语句格式如下:

returnType methodName(para1,para2,……) throws exception

示例:

package 测试;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JApplet;
public class test extends JApplet{
	static void throwOne() throws IllegalAccessException{
		throw new IllegalAccessException("自编异常");
	}
	public void paint(Graphics g) {
		Graphics2D g2=(Graphics2D)g;
		try {
			throwOne();
		}
		catch(IllegalAccessException e) {
			g2.drawString("发生异常"+e, 20,20);
		}
	}
}

 


 

 

 

 

 

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

 

发表评论