ITEEDU

12-6:使用JToolBar组件:

JToolBar的类层次结构图:
 java.lang.Object
   --java.awt.Component
    --java.awt.Container
      --javax.swing.JComponent
       --javax.swing.JToolBar

ToolBar的功能是用来放置各种常用的功能或控制组件,这个功能在各类软件中都可以很轻易的看到.一般我们在设计软件时,会将 所有功能依类放置在菜单中(JMenu),但当功能数量相当多时,可能造成用户操作一个简单的操作就必须繁复的寻找菜单中相关的功能 ,这将造成用户操作上的负担.若我们能将一般常用的功能以工具栏方式呈现在菜单下,让用户很快得到他想要的功能,不仅增加用户 使用软件的意愿,也加速工作的运行效率.这就是使用ToolBar的好处.我们现在来看看JTooBar的构造方式.

JToolBar构造函数:
  • JToolBar():建立一个新的JToolBar,位置为默认的水平方向.
  • JToolBar(int orientation):建立一个指定的JToolBar.
  • JToolBar(String name):建立一个指定名称的JToolBar.
  • JToolBar(String name,int orientation):建立一个指定名称和位置的JToolBar.

12-6-1:构造JToolBar组件:

在使用JToolBar时一般都采用水平方向的位置,因此我们在构造时多是采用上表中的第一种构造方式来建立JToolBar.如果需要 改变方向时再用JToolBar内的setOrientation()方法来改变设置,或是以鼠标拉动的方式来改变JToolBar的位置.我们来看下面的例 子:

JToolBar1.java
 import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.incors.plaf.alloy.*;
import com.incors.plaf.alloy.themes.glass.*;

public class JToolBar1 extends JFrame {

	JTextArea theArea = null;
	static final String ComboStr[] = { "Times New Roman", "Dialog", "宋体", "黑体",
			"楷体" };

	public JToolBar1() {

		super("JToolBar1");
		theArea = new JTextArea();
		theArea.setEditable(false);
		getContentPane().add(new JScrollPane(theArea));
		JMenuBar MBar = new JMenuBar();
		MBar.setOpaque(true);

		JMenu mfile = buildFileMenu();
		JToolBar theBar = buildToolBar();
		this.getContentPane().add(theBar, BorderLayout.NORTH);// 将构造好的JToolBar放置到窗口上.

		MBar.add(mfile);// 将JMenu加入到JMenuBar中
		setJMenuBar(MBar);// 将JMenuBar设置到窗口中.
	}// end of JToolBar1()

	public JMenu buildFileMenu() {

		JMenu thefile = new JMenu("File");
		thefile.setMnemonic('F');

		JMenuItem newf = new JMenuItem("New", new ImageIcon("icons/new24.gif"));
		JMenuItem open = new JMenuItem("Open",
				new ImageIcon("icons/open24.gif"));
		JMenuItem close = new JMenuItem("Close", new ImageIcon(
				"icons/close24.gif"));
		JMenuItem quit = new JMenuItem("Exit",
				new ImageIcon("icons/exit24.gif"));

		newf.setMnemonic('N');
		open.setMnemonic('O');
		close.setMnemonic('L');
		quit.setMnemonic('X');

		newf.setAccelerator(KeyStroke.getKeyStroke('N',
				java.awt.Event.CTRL_MASK, false));
		open.setAccelerator(KeyStroke.getKeyStroke('O',
				java.awt.Event.CTRL_MASK, false));
		close.setAccelerator(KeyStroke.getKeyStroke('L',
				java.awt.Event.CTRL_MASK, false));
		quit.setAccelerator(KeyStroke.getKeyStroke('X',
				java.awt.Event.CTRL_MASK, false));

		newf.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theArea.append("- MenuItem New Performed -\n");
			}
		});

		open.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theArea.append("- MenuItem Open Performed -\n");
			}
		});

		close.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theArea.append("- MenuItem Close Performed -\n");
			}
		});

		quit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

		thefile.add(newf);
		thefile.add(open);
		thefile.add(close);
		thefile.addSeparator();
		thefile.add(quit);

		return thefile;
	}// end of buildFileMenu()

	public JToolBar buildToolBar() {
     
     JToolBar toolBar = new JToolBar();
     toolBar.setFloatable(true);//设置JToolBar可否浮动.
     
     //分别构造三个ToolBarAction的类组件,准备将这三个组件设置到JToolBar中.ToolBaarAction类是我们自己编写的inner
     //  class,这个inner class在程序后半部份,这个类继承AbstractAction,AbstractAction是一个抽象类,实现Action 
     //interface,而Action interface又继承ActionListener interface又继承AActionListener interface,因此可直接在
     //AbstractAction中覆写actionPerformed()方法,处理ActionEvent事件.在JToolBar中有一个add(Action a)方法,只要传入
     //Action参数就可以得到一个JButton对象,因此在程序中下面的98,100,102就是以这样的方式来构造出JToolBar上的按钮组
     //件.
     ToolBarAction tba_new   = new ToolBarAction("new",new ImageIcon("icons/new24.gif"));
     ToolBarAction tba_open  = new ToolBarAction("open",new ImageIcon("icons/open24.gif"));
     ToolBarAction tba_close = new ToolBarAction("close",new ImageIcon("icons/close24.gif"));
     
     //99,101,103利用setActionCommand()方法分别设置各个组件被触发事件后所返回的字符串信息.                                                
     JButton JB;
     98	  JB = toolBar.add(tba_new);//将ToolBarAction组件加入JToolBar中.
     99	  JB.setActionCommand("#TooBar_NEW performed!");
     100	  JB = toolBar.add(tba_open);//将ToolBarAction组件加入JToolBar中.
     101	  JB.setActionCommand("#ToolBar_OPEN performed!");
     102	  JB = toolBar.add(tba_close);//将ToolBarAction组件加入JToolBar中.
     103	  JB.setActionCommand("#ToolBar_CLOSE performed!");
     
     toolBar.addSeparator();//在JToolBar加上分隔线,如同在JMenu上利用addSeparator()方法加上分隔线一样,不同的是在
     //JMenu中分隔线是以灰色直线的样式表现,而在JToolBar中则是以一小段空来表示.
     
     ToolBarAction tba_B  = new ToolBarAction("bold",new ImageIcon("icons/bold24.gif"));
     ToolBarAction tba_I  = new ToolBarAction("italic",new ImageIcon("icons/italic24.gif"));
     ToolBarAction tba_U  = new ToolBarAction("underline",new ImageIcon("icons/underline24.gif")); 
     JB = toolBar.add(tba_B);//重复上面的操作
     JB.setActionCommand("#ToolBar_Bold performed!");
     JB = toolBar.add(tba_I);
     JB.setActionCommand("#ToolBar_Italic performed!");
     JB = toolBar.add(tba_U);
     JB.setActionCommand("#ToolBar_Underline performed!");
     
     toolBar.addSeparator(); 
     //在JToolBar中加入一个JLabel组件.   
     JLabel JLfont = new JLabel("Font Type");
     toolBar.add(JLfont);
     toolBar.addSeparator();
     //利用上面定义的ComboStr数建立一个JComboBox组件.
     JComboBox jcb = new JComboBox(ComboStr);
     //将JComboBar加入事件处理模式.这里是将所选到的组件名称填入JTextArea中.
     jcb.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
     theArea.append("*Combobox "+((JComboBox)e.getSource()).getSelectedItem()+" 
     performed!\n");
     }});
     //在JToolBar中加入一个JComboBox组件.
     toolBar.add(jcb);
     
     return toolBar;
     }//end of buildToolBar()

	public static void main(String[] args) {
		SwingUtil.setLookAndFeel();
		JFrame F = new JToolBar1();
		F.setSize(430, 200);
		F.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});// end of addWindowListener
		F.setVisible(true);
	} // end of main

	class ToolBarAction extends AbstractAction {

		public ToolBarAction(String name, Icon icon) {
			super(name, icon);
		}

		// 对于JToolBar上按钮的事件处理是将组件的ActionCommand返回值字符串加入JTextArea中.
		public void actionPerformed(ActionEvent e) {

			try {
				theArea.append(e.getActionCommand() + "\n");
			} catch (Exception ex) {
			}
		}
	}// end of inner class ToolBarAction
}// end of class JToolBar1

class SwingUtil {
	public static final void setLookAndFeel() {
		try {
			Font font = new Font("JFrame", Font.PLAIN, 12);
			Enumeration keys = UIManager.getLookAndFeelDefaults().keys();

			while (keys.hasMoreElements()) {
				Object key = keys.nextElement();
				if (UIManager.get(key) instanceof Font) {
					UIManager.put(key, font);
				}
			}
			AlloyLookAndFeel.setProperty("alloy.isLookAndFeelFrameDecoration",
					"true");
			AlloyTheme theme = new GlassTheme();
			LookAndFeel alloyLnF = new AlloyLookAndFeel(theme);
			UIManager.setLookAndFeel(alloyLnF);
		} catch (UnsupportedLookAndFeelException ex) {
			ex.printStackTrace();
		}
	}
}

在上面这个程序中,我们利用AbstractAction抽象类来构造JToolBar上的JButton组件,这个做法看起来较为陌生,下面我们详细 探讨其中隐含的意义.我们曾提到AbstractAction是一个抽象类,实现Action界面,而Action界面又继承ActionListener界面,因此 AbstractAction类具有侦听ActionEvent的功能,我们可以覆写actionPerformed()方法来处理ActionEvent事件.然而使用 AbstractAction抽象类有什么好处呢?通常一个软件在设计时会因用户习惯,产生不同的操作方式却能达到相同的功能,例如文书编辑 器中,copy功能可能在菜单中出现,也可能在工具栏上出现,甚至在快显菜单(Popup Menu)中出现,虽然出现的方式不一样,但均能达到 copy的功能.若以我们之前的事件处理方法,我们必须为每种出现方式实现copy功能,造成程序代码重复性太高,不易阅读也不美观, 相反的,若我们以AbstractAction抽象类来覆写actionPerformed()方法,我们只需要为每一种功能编写一次程序代码即可,因为 JToolBar,JMenu,JPopupMenu类均有add(Action a)方法,可利用相同的AbstractAction类构造出个别不同的组件.下面范例我们利用 这个概念让用户"按我"选项时,均使用同一个actionPerformed()方法:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JToolBar2 extends JFrame {

	JTextArea theArea = null;
	ToolBarAction pushAction = null;

	public JToolBar2() {

		super("JToolBar2");
		theArea = new JTextArea();
		theArea.setEditable(false);
		getContentPane().add(new JScrollPane(theArea));
		JMenuBar MBar = new JMenuBar();
		MBar.setOpaque(true);

		pushAction = new ToolBarAction("按我", null);
		JMenu mfile = buildFileMenu();
		JToolBar theBar = buildToolBar();
		this.getContentPane().add(theBar, BorderLayout.NORTH);

		MBar.add(mfile);
		setJMenuBar(MBar);
	}// end of JToolBar2()

	public JMenu buildFileMenu() {

		JMenu thefile = new JMenu("File");
		thefile.setMnemonic('F');
		thefile.add(pushAction);

		return thefile;
	}// end of buildFileMenu()

	public JToolBar buildToolBar() {

		JToolBar toolBar = new JToolBar();
		toolBar.setFloatable(true);
		toolBar.add(pushAction);

		return toolBar;
	}// end of buildToolBar()

	public static void main(String[] args) {

		JFrame F = new JToolBar2();
		F.setSize(430, 200);
		F.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});// end of addWindowListener
		F.setVisible(true);
	} // end of main

	class ToolBarAction extends AbstractAction {

		public ToolBarAction(String name, Icon icon) {
			super(name, icon);
		}

		public void actionPerformed(ActionEvent e) {

			try {
				theArea.append("不管用哪种方式执行\"按我\",都会出现这句!!" + "\n");
			} catch (Exception ex) {
			}
		}
	}// end of inner class ToolBarAction
}// end of class JToolBar2

说明:

1.利用ToolBarAction类分别建立JToolBar上的JButton与JMenu上的JMenuItem组件,ToolBarAction类继承AbstractAction抽象 类,并覆写actionPerformed()方法.读者在读完JPopupMenu小节后,可将JPopupMenu的功能加入此范例中.

2. 从上面程序中可看出,一般事件处理方式:先产生个别组件,再利用addActionListener()方法侦听ActionEvent事件,最后覆写 actionPerformed()方法.然而以继承AbstractAction抽象类方式处理相同的事件,可以看出程序代码精简许多.读者可比较之间的差 异性.