ITEEDU

12-7:使用JPopupMenu组件.

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

JPopupMenu是一种特别形式的Menu,其性质与Menu几乎完全相同,但是PopupMenu并不固定在窗口的任何一个位置,而是由鼠标指 针和系统判断决定PopupMenu要出现在哪里.相信大家在使用许多软件时都有用过Popupmenu的功能,例如在使用Word文书编辑器软件 时,当我们在编辑区域的任一处按下鼠标右键,就会跳出一个PopupMenu菜单.

JPopupMenu构造函数:

  • JPopupMenu():建立一个新的JPopupMenu;
  • JPopupMenu(String label):建立一个指定标题的JPopupMenu.

12-7-1:构造JPopupMenu组件:

由一表中我们可以知道JPopupMenu的构造方法并不复杂,两种构造方法的差异只在于是否赋予JPopupMenu一个标题文字.我们马上来 看下面这个范例,了解如何应用JPopupMenu.

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

public class JPopupMenu1 extends JFrame {

	JTextArea theArea = null;
	static final String ComboStr[] = { "Times New Roman", "Dialog", "宋体", "黑体",
			"楷体" };
	JPopupMenu Popup = null;// 声明一个全局(Global)并设置初始值为null的JPopupMenu组件.

	public JPopupMenu1() {

		super("JPopupMenu1");
		theArea = new JTextArea();
		theArea.setEditable(false);
		this.getContentPane()
				.add(new JScrollPane(theArea), BorderLayout.CENTER);
		JMenuBar MBar = new JMenuBar();
		MBar.setOpaque(true);
		JMenu mfile = buildFileMenu();
		JToolBar theBar = buildToolBar();
		this.getContentPane().add(theBar, BorderLayout.NORTH);
		PopupPanel pp = new PopupPanel();// new一个PopupPanel组件来放置JPopupMenu.
		this.getContentPane().add(pp, BorderLayout.SOUTH); // 将PopupPanel组件放置到窗口中.

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

	/*****************
	 * begin********************** 分别建立程序中菜单,工具栏和事件处理模式的部份,我们在此不再加以说明.
	 ****************************************/
	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);
      
      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"));
      
      JButton JB;
      JB = toolBar.add(tba_new);
      JB.setActionCommand("#TooBar_NEW performed!");
      JB.setToolTipText((String)tba_new.getValue(Action.NAME));
      JB = toolBar.add(tba_open);
      JB.setActionCommand("#ToolBar_OPEN performed!");
      JB.setToolTipText((String)tba_open.getValue(Action.NAME));
      JB = toolBar.add(tba_close);
      JB.setActionCommand("#ToolBar_CLOSE performed!");
      JB.setToolTipText((String)tba_close.getValue(Action.NAME));
      
      toolBar.addSeparator();
      
      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.setToolTipText((String)tba_B.getValue(Action.NAME));
      JB = toolBar.add(tba_I);
      JB.setActionCommand("#ToolBar_Italic performed!");
      JB.setToolTipText((String)tba_I.getValue(Action.NAME));    
      JB = toolBar.add(tba_U);
      JB.setActionCommand("#ToolBar_Underline performed!");
      JB.setToolTipText((String)tba_U.getValue(Action.NAME));
      
      toolBar.addSeparator();    
      JLabel JLfont = new JLabel("Font Type");
      toolBar.add(JLfont);
      toolBar.addSeparator();
      JComboBox jcb = new JComboBox(ComboStr);
      jcb.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
      theArea.append("*Combobox "+((JComboBox)e.getSource()).getSelectedItem()+"
      performed!\n");
      }});
      toolBar.add(jcb);
      
      return toolBar;
      }//end of buildToolBar()

	/*****************
	 * End********************** 分别建立程序中菜单,工具栏和事件处理模式的部份,我们在此不再加以说明.
	 ****************************************/

	public static void main(String[] args) {
		SwingUtil.setLookAndFeel();
		JFrame F = new JPopupMenu1();
		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(e.getActionCommand() + "\n");
			} catch (Exception ex) {
			}
		}
	}// end of inner class ToolBarAction

	/*
	 * 本方法建立inner class
	 * PopupPanel.这个类继承JPanel并实作MouseListener,PopupMenuListener,ActionListener和
	 * ActionListener等3个Listener
	 * .MouseListener为处理鼠标事件的Listener,PopupMenuListener为Popup菜单事件的Listener,
	 * ActionListener则是大家最熟悉用来处理JMenuItem事件的Listener.
	 */
	class PopupPanel extends JPanel implements MouseListener,
			PopupMenuListener, ActionListener {

		public PopupPanel() {

			Popup = new JPopupMenu();// new 一个新的JPopupMenu.

			JMenuItem theItem;

			// 分别建立四个JMenuItem和其事件处理模式将将JMenuItem加入JPopupMenu中.
			Popup.add(theItem = new JMenuItem("Cut", new ImageIcon(
					"icons/cut24.gif")));// 建立JMenuItem组件.
			theItem.addActionListener(this);// 将JMenuItem组件加入事件处理模式.
			Popup.add(theItem = new JMenuItem("Copy", new ImageIcon(
					"icons/copy24.gif")));
			theItem.addActionListener(this);
			Popup.add(theItem = new JMenuItem("Paste", new ImageIcon(
					"icons/paste24.gif")));
			theItem.addActionListener(this);
			Popup.addSeparator();// 在JPopupMenu中加入分隔线,我们在前面有提到JPopupMenu和Menu大致上的性质是一样的,所以
			// 在JPopupMenu中一样是以JMenuItem来当作选项的组件.
			Popup.add(theItem = new JMenuItem("Page Setup..."));
			theItem.addActionListener(this);

			// 利用setBorder()方法将BevelBorder类当作参数传入,使JPopupMenu产生立体边框浮起的效果.我们也可以将参数设置改
			// 为BevelBorder.LOWERED使得JPopupMenu产生立体边框凹陷的效果.
			Popup.setBorder(new BevelBorder(BevelBorder.RAISED));

			Popup.addPopupMenuListener(this); // 将JPopupMenu组件加入PopupMenu事件处理模式中.
			addMouseListener(this);// 将PopupPanel类加入Mouse事件处理模式中.
			theArea.addMouseListener(this);// 后面有说明

		}// end of PopupPanel()

		/*
		 * 由于PopupPanel这个inner
		 * class中实作了MouseListener,因此需要覆写mouseClicked(),mousePressed(),
		 * mouseReleased
		 * (),mouseEntered()和mouseExited()等5个方法.在这个范例里当mouseClicked(
		 * ),mousePressed()
		 * 和mouseReleased()等3个方法被触发时会调用checkPopup()方法来判断是否要将PopupMenu输出来.
		 */
		public void mouseClicked(MouseEvent me) {
			checkPopup(me);
		}

		public void mousePressed(MouseEvent me) {
			checkPopup(me);
		}

		public void mouseReleased(MouseEvent me) {
			checkPopup(me);
		}

		public void mouseEntered(MouseEvent me) {
		}

		public void mouseExited(MouseEvent me) {
		}

		/*
		 * checkPopup()方法.其中,在程序中利用isPopupTrigger()方法判断PopupMenu是否已经输出.若没有,则在程序中利用
		 * show()方法将PopupMenu输出目前鼠标指针(利用getX()和getY()方法得知)的位置上.
		 */
		private void checkPopup(MouseEvent me) {
			if (me.isPopupTrigger()) {
				Popup.show(me.getComponent(), me.getX(), me.getY());
			}
		}// end of checkPopup()

		/*
		 * 由于PopupPanel这个inner
		 * class实作了PopupMenuListener,因此需要覆写popupMenuWillBecomeVisible(),
		 * popupMenuWillBecomeInvisible
		 * ()方法和popupMenuCanceled()等3个方法.在这个范例里当这3个方法被触发后会在JTextArea中加入一个信息.
		 */
		public void popupMenuWillBecomeVisible(PopupMenuEvent pme) {
			theArea.append("-PopupMenu Visibel!\n");
		}

		public void popupMenuWillBecomeInvisible(PopupMenuEvent pme) {
			theArea.append("-PopupMenu Invisibel!\n");
		}

		public void popupMenuCanceled(PopupMenuEvent pme) {
			theArea.append("-PopupMenu Hidden!\n");
		}

		// 当某个JMenuItem被触发后会在JTextArea中加入一个信息.
		public void actionPerformed(ActionEvent ae) {
			theArea.append("+Popup " + ae.getActionCommand() + " performed!\n");
		}
	}// end of inner class PopupPanel
}// end of class JPopupMenu1

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();
		}
	}
}
说明:

(1):由于JPopupMenu只是一种Menu的组件,因此在使用JPopupMenu时我们都需要一个Container来放置JPopupMenu,在这里这们 选择使用JPanel组件来作为JPopupMenu的Container.

(2):这个程序的运行结果可发现JPopupMenu只有在JTextArea下缘,也就是JPanel的部份才有作用,因为我们并没有在JTextArea 中加入addMouseListener()方法,你可以在PopupPanel()构造函数中加入: theArea.addMouseListener(this); 这行,就能够解决在JTextArea上无法显示JPopupMenu的问题.