1. 程式人生 > >Java圖形程式設計學習(4)Swing元件

Java圖形程式設計學習(4)Swing元件

1、元件內部的設計—以Swing按鈕為例

背景:MVC模式,即模型-檢視-控制器模式。Swing元件底層大多數都用到了該模式。接下來以按鈕為例分析這種模式。

(1)元件的模型類,一般是實現以Model結尾的介面。按鈕的模型類實現了ButtonModel介面。實現了該介面的類可以設定

ButtonModel介面中定義的按鈕的各種屬性,定義按鈕的狀態。DefaultButtonModel類就實現了這個介面。

(2)模型不儲存按鈕的圖示,即僅憑模型不能知道按鈕的外觀,這些外觀由檢視控制。

(3)控制器負責處理使用者輸入事件,如點選滑鼠。然後覺得是否把這些事件轉化成對模型或檢視的改變。並不是所有的元件

都有專門的控制器物件。

2、佈局管理器

 作用:通常元件放置在容器中,佈局管理器決定容器中的元件具體放置的位置和大小。

分類:

流佈局管理器(面板的預設佈局管理器):居中,一行滿了會換行。

邊框佈局管理器(JFrame的內容窗格的預設佈局管理器):選擇將元件放在內容窗格的中部,北部等。

網格佈局管理器:按行列排列所有的元件,並且每個單元的大小是一樣的。

注:可以組合使用

package comp;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

/**
 * 設計一個計算器
 */
public class CalculatorPanel extends JPanel{
	private JButton display;
	private JPanel panel;
	private double result;
	private String lastCommand;
	private boolean start;
	
	//返回元件的首選大小
	public Dimension getPreferredSize() {
		return new Dimension(300,200 );
	}
	
	public CalculatorPanel() {
		//構造一個新的邊界佈局,在元件之間沒有間隙。
		setLayout( new BorderLayout() );
		
		result = 0;
		lastCommand = "=";
		start = true;
		
		//用一個不可以點選的按鈕作為計算器的顯示欄
		display = new JButton("0");
		display.setEnabled(false);
		add( display, BorderLayout.NORTH );//邊框佈局的使用
		
		//數字鍵和符號鍵會發出兩種事件,分別處理
		ActionListener insert = new InsertAction();
		ActionListener command = new CommandAction();
		
		panel = new JPanel();
		panel.setLayout(new GridLayout(4, 4));//網格佈局的使用,4行4列
		
		//向panel中新增按鈕,並且該方法會讓按鈕繫結一個監聽器
		addButton("7", insert);
		addButton("8", insert);
		addButton("9", insert);
		addButton("/", command);
		
		addButton("4", insert);
		addButton("5", insert);
		addButton("6", insert);
		addButton("*", command);
		
		addButton("1", insert);
		addButton("2", insert);
		addButton("3", insert);
		addButton("-", command);
		
		addButton("0", insert);
		addButton(".", insert);
		addButton("=", command);
		addButton("+", command);
		
		add( panel, BorderLayout.CENTER );//邊框佈局的使用
		
		
	}

	private void addButton(String label, ActionListener listener) {
		JButton button = new JButton( label );
		button.addActionListener(listener);
		panel.add(button);
	}
	
	private class InsertAction implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			//返回與此操作相關聯的命令字串
			String input = e.getActionCommand();
			//開始時start是true,若按了任意數字鍵,先將顯示欄清空
			if( start ) {
				display.setText("");
				start = false;
			}
			//將原有的數字和現在點選的數字鍵字元拼接
			display.setText(display.getText() + input);
		}
	}
	
	private class CommandAction implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			String command = e.getActionCommand();
			//剛開始時的符號只有 - 能算數
			if( start ) {
				//這裡-是負號的意思,表示負數
				if( command.equals("-") ) {
					display.setText(command);
					start = false;
				}else {
					lastCommand = command;
				}
			}else {
				//預設設定了一個result和一個輸入做運算,得到的結果放入result中
				calculate(Double. parseDouble( display.getText() ));
				lastCommand = command;
				start = true;
			}
		}
	}
	
	public void calculate(double x) {
		if( lastCommand.equals("+") ) result += x;
		else if( lastCommand.equals("-") ) result -= x;
		else if( lastCommand.equals("*") ) result *= x;
		else if( lastCommand.equals("/") ) result /= x;
		else if( lastCommand.equals("=") ) result = x;
		display.setText(""+result);
	}
}
package comp;

import java.awt.EventQueue;

import javax.swing.JFrame;



public class CalFrame extends JFrame{
	
	public CalFrame() {
		add(new CalculatorPanel());
		pack();//更加元件的首選大小,調整視窗
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new CalFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

3、文字輸入

(1)文字域:只接受單行文字的輸入

需要掌握的API:

JTextField textField = new JTextField( "hahahha", 20 ); 

JTextField textField = new JTextField( 20 ); 

textField.setText("Hello hahaha");

String text = textField.getText().trim();//返回文字域中的內容,去掉前後空格

(2)密碼域:只接受單行文字的輸入,且輸入內容不會顯示出來

需要掌握的API:

JPasswordField(String text, int col);

void setEchoChar(char echo);//設定回顯字元,0表示預設的回顯字元

char[] getPassword(); //返回密碼域中的文字

(3)文字區:接受多行文字

需要掌握的API:

JTextArea textArea = new JTextArea(8, 40); //8行40列的文字區

textArea.setLineWrap(true);//文字超出文字區會被剪裁,開啟換行特性避免被裁剪;換行只是視覺效果,文字中間沒有換行符

JScrollPane scrollPane = new JScrollPane(textArea );//文字區沒有滾動條,將文字區放到滾動窗格中

package comp;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

public class TextComFrame extends JFrame{
	
	public TextComFrame() {
		JTextField textField = new JTextField();
		JPasswordField passwordField = new JPasswordField();
		
		JPanel northPanel = new JPanel();
		//設定面板是2*2的網格佈局
		northPanel.setLayout(new GridLayout(2,2));
		//給textField文字框新增一個標籤;標籤位置在第一行的第一個網格中居中
		northPanel.add(new JLabel("User name: ", SwingConstants.CENTER));
		northPanel.add(textField);
		//給passwordField文字框新增一個標籤;
		northPanel.add(new JLabel("Password: ", SwingConstants.CENTER));
		northPanel.add(passwordField);
		
		add( northPanel, BorderLayout.NORTH );
	
		JTextArea textArea = new JTextArea( 8,20 );
		JScrollPane scrollPane = new JScrollPane( textArea );
		add( scrollPane, BorderLayout.CENTER );
		
		JPanel southPanel = new JPanel();
		JButton insertButton = new JButton( "Insert" );
		southPanel.add(insertButton);
		insertButton.addActionListener(
				event -> textArea.append(
						"User name: " + textField.getText() +
						" Password: " +new String(passwordField.getPassword()) + "\n" )
		);
		add( southPanel, BorderLayout.SOUTH );
		
		pack();
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new TextComFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

4、選擇元件

(1)複選框:選中或者不選;

JCheckBox( String label );//構造一個複選框,預設是沒有被選中

JCheckBox( String label, Icon icon );

JCheckBox( String label, boolean state );//用給定的標籤和初始化狀態構造一個複選框

boolean isSelected();

void setSelected( boolean state );//設定複選框的狀態

(2)單選鈕組:只選擇多個選項中的一個;選擇另一個前一個自動取消;

JRadioButton( String label, Icon icon ); //構造一個單選鈕,預設是沒有被選中

JRadioButton( String label, boolean state ); //用給定的標籤和初始化狀態構造一個單選鈕

void add( AbstractButton b ); //將按鈕新增到組中

ButtonModel getSelection(); //返回被選中的按鈕的按鈕模型

String getActionCommand(); //返回按鈕模型的動作命令

void setActionCommand( String s ); //設定按鈕及模型的動作命令

注意:一個視窗,若有多組單選按鈕,就需要用視覺化的形式指明哪些按鈕屬於同一組,邊框解決該問題。

(3)組合框:若覺得單選按鈕佔據的螢幕空間太大,就可以使用組合框(下拉框)。

JComBox<String> comb = new JComBox<String>();

boolean isEditable();

void setEditable( boolean b );

void addItem( Object item );

void insetItemAt( Object item, int index );

void removeItem( Object item );

void removeItemAt( int index );

void removeAllItems();

Object getSelectedItem();

(4)滑動條:讓使用者從一組離散值中進行選擇;

JSlider();//預設的滑動條:方向水平,0-100,初始值50

JSlider( int direction );

JSlider( int min, int max );

JSlider( int min, int max, int initialValue );

JSlider( int direction, int min, int max, int initialValue );

void setPaintTicks( boolean b );//顯示標尺

void setMajorTickSpacing( int units );//用給定的滑動條單位的倍數設定大標尺

void setMinorTickSpacing( int units );//用給定的滑動條單位的倍數設定小標尺

void setPaintLabels( boolean b ); //顯示標尺標籤

void setLabelTable( Dictionary table );//設定用於作為標尺標籤的元件

void setSnapToTicks( boolean b ); //true 則每一次調整後滑塊都要對齊到最接近的標尺處

void setPaintTrack( boolean b ); //true 則顯示滑動條滑動的軌跡

package comp;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionListener;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class CheckBoxFrame extends JFrame{
	private JLabel label;
	//複選框 bold; 選中則使文字變粗
	private JCheckBox bold;
	//複選框italic; 選中則使文字斜體
	private JCheckBox italic;
	
	public CheckBoxFrame() {
		label = new JLabel("-----------用來測試複選框的作用---------");
		label.setFont( new Font("Serif", Font.BOLD, 24) );
		add( label, BorderLayout.CENTER );
		
		//監聽器對複選框的響應;選中則改變標籤字型
		ActionListener listener = event ->{
			int mode = 0;
			if( bold.isSelected() ) mode += Font.BOLD;
			if( italic.isSelected() ) mode += Font.ITALIC;
			label.setFont(new Font( "Serif", mode, 24 ));
		};
		
		JPanel buttonPanel = new JPanel();
		bold = new JCheckBox( "Bold" );
		bold.addActionListener(listener);
		bold.setSelected(true);
		buttonPanel.add(bold);
		
		italic = new JCheckBox( "Italic" );
		italic.addActionListener(listener);
		buttonPanel.add(italic);
		
		add( buttonPanel, BorderLayout.SOUTH );
		pack();
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new CheckBoxFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
	
}

package comp;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class RadioButtonFrame extends JFrame{
		private JLabel label;
		private ButtonGroup group;
		private JPanel buttonPanel;
		
		public RadioButtonFrame() {
			label = new JLabel( "測試單選按鈕例子" );
			label.setFont(new Font( "Serif", Font.PLAIN, 36 ));
			add( label, BorderLayout.CENTER );
			
			buttonPanel  = new JPanel();
			group = new ButtonGroup();
			
			addRadioButton("Small", 8);
			addRadioButton("Medium", 12);
			addRadioButton("Large", 18);
			addRadioButton("Extra large", 36);
			
			add( buttonPanel, BorderLayout.SOUTH );
			pack();
		}
		
		public void addRadioButton( String name, int size ) {
			boolean selected = size == 36;
			JRadioButton button = new JRadioButton( name, selected );
			group.add(button);
			buttonPanel.add(button);
			
			ActionListener listener = event -> label.setFont(new Font( "Serif", Font.PLAIN, size ));
			button.addActionListener(listener);
		}
		
		public static void main(String[] args) {
			EventQueue.invokeLater(new Runnable() {
				@Override
				public void run() {
					JFrame frame = new RadioButtonFrame();//初始化視窗
					frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
					frame.setVisible(true);//顯示視窗
				}
			});
		}
		
	}

package comp;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.Border;

public class BorderFrame extends JFrame{
	private JPanel demoPanel;
	private JPanel buttonPanel;
	private ButtonGroup group;
	
	public BorderFrame() {
		demoPanel = new JPanel();
		buttonPanel = new JPanel();
		group = new ButtonGroup();
		
		addRadioButton( "Lowered bevel", BorderFactory.createLoweredBevelBorder() );
		addRadioButton( "Raised bevel", BorderFactory.createRaisedBevelBorder() );
		addRadioButton( "Etched bevel", BorderFactory.createEtchedBorder() );
		addRadioButton( "Line bevel", BorderFactory.createLineBorder(Color.BLUE) );
		addRadioButton( "Matte bevel", BorderFactory.createMatteBorder(10, 10, 10, 10,Color.BLUE ) );
		addRadioButton( "Empty bevel", BorderFactory.createEmptyBorder() );
		
		Border etched = BorderFactory.createEtchedBorder();
		Border titled = BorderFactory.createTitledBorder(etched, "Border types" );
		buttonPanel.setBorder(titled);
		
		setLayout(new GridLayout(2, 1));
		add(buttonPanel);
		add(demoPanel);
		pack();
	}
	
	public void addRadioButton( String buttonName, Border b ) {
		boolean selected = buttonName == "Empty bevel";
		JRadioButton button = new JRadioButton( buttonName, selected );
		//給指定的按鈕,設定邊框
		button.addActionListener(event -> demoPanel.setBorder(b));
		group.add(button);
		buttonPanel.add(button);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new BorderFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

package comp;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class ComboBoxFrame extends JFrame{
	private JComboBox<String> faceCombo;
	private JLabel label;
	
	public ComboBoxFrame() {
		label = new JLabel("測試下拉框的例子");
		label.setFont(new Font( "Serif", Font.PLAIN,24 ));
		add( label, BorderLayout.CENTER );
		
		faceCombo = new JComboBox<String>();
		faceCombo.addItem("Serif");
		faceCombo.addItem("SansSerif");
		faceCombo.addItem("Monospaced");
		faceCombo.addItem("Dialog");
		faceCombo.addItem("DialogInput");
		
		faceCombo.addActionListener(
				event -> label.setFont(new Font(faceCombo.getItemAt(faceCombo.getSelectedIndex()), Font.PLAIN, 24))
		);
		
		faceCombo.addActionListener(
				event -> System.out.println(faceCombo.getItemAt(faceCombo.getSelectedIndex()))
		);
		
		
		JPanel comboPanel = new JPanel();
		comboPanel.add(faceCombo);
		add(comboPanel, BorderLayout.SOUTH );
		pack();
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new ComboBoxFrame();//初始化視窗
				frame.setSize(300, 200);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

package comp;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.util.Dictionary;
import java.util.Hashtable;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeListener;

public class SliderFrame  extends JFrame{
	private JPanel sliderPanel;
	private JTextField textField;
	private ChangeListener listener;
	
	
	public SliderFrame() {
		sliderPanel = new JPanel();
		sliderPanel.setLayout(new GridLayout(10,1));
		
		//通過監聽器獲取滑動條當前值
		listener = event -> {
			JSlider source = (JSlider)event.getSource();
			textField.setText(""+source.getValue());
		};
		
		//第一個
		JSlider slider = new JSlider();
		textField = new JTextField();
		addSlider( slider, "Plain" );
		
		//第二個
		slider = new JSlider();
		slider.setPaintTicks(true);//顯示標尺
		slider.setMajorTickSpacing(20);//大格為20單位
		slider.setMinorTickSpacing(5);//小格為5單位
		addSlider( slider, "Ticks" );
		
		//第三個
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setSnapToTicks(true);//每一次調整後,滑塊都會對齊到最近的標尺處
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(5);
		addSlider( slider, "Snap to ticks" );
		
		//第4個
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(5);
		slider.setPaintTrack(false);//不顯示滑動條滑動的軌跡
		addSlider( slider, "No track" );
		
		//第5個
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(5);
		slider.setInverted(true);//最左端是100,最右端是0
		addSlider( slider, "Inverted" );
		
		//第6個
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);//設定標尺標籤,預設是數字,標明大格單位
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(5);
		addSlider( slider, "Labels" );
		
		//第6個
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(5);
		Dictionary<Integer, Component>  labelTable = new Hashtable<>();
		labelTable.put(0, new JLabel("A"));
		labelTable.put(20, new JLabel("B"));
		labelTable.put(40, new JLabel("C"));
		labelTable.put(60, new JLabel("D"));
		labelTable.put(80, new JLabel("E"));
		labelTable.put(100, new JLabel("F"));
		slider.setLabelTable(labelTable);
		addSlider(slider, "Custom labels");
		
		//第7個;沒有對應圖片故不顯示圖片標籤
		slider = new JSlider();
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		slider.setSnapToTicks(true);
		slider.setMajorTickSpacing(20);
		slider.setMinorTickSpacing(20);
		labelTable = new Hashtable<>();
		labelTable.put(0, new JLabel(new ImageIcon("nine.gif")));
		labelTable.put(20, new JLabel(new ImageIcon("nine.gif")));
		labelTable.put(40, new JLabel(new ImageIcon("nine.gif")));
		labelTable.put(60, new JLabel(new ImageIcon("nine.gif")));
		labelTable.put(80, new JLabel(new ImageIcon("nine.gif")));
		labelTable.put(100, new JLabel(new ImageIcon("nine.gif")));
		slider.setLabelTable(labelTable);
		addSlider(slider, "Icon labels");
				
		
		textField = new JTextField();
		add( sliderPanel, BorderLayout.CENTER );
		add( textField, BorderLayout.SOUTH );//textField用來顯示滑塊所指的資料
		
		pack();
		
	}
	
	//新增滑動條的方法
	public void addSlider( JSlider s, String description ) {
		s.addChangeListener(listener);
		JPanel panel = new JPanel();
		panel.add(s);
		panel.add(new JLabel(description));
		panel.setAlignmentX(Component.LEFT_ALIGNMENT);
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridy = sliderPanel.getComponentCount();
		gbc.anchor = GridBagConstraints.WEST;
		sliderPanel.add(panel, gbc);
		
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new SliderFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

5、選單

package comp;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;

public class MenuFrame extends JFrame{
	private static final int DEFAULT_WIDTH = 300;
	private static final int DEFAULT_HEIGHT = 200;
	private Action saveAction;
	private Action saveAsAction;
	private JCheckBoxMenuItem readonlyItem;
	private JPopupMenu popup;
	
	//動作
	class TestAction extends AbstractAction{
		public TestAction( String name ) {
			super( name );
		}
		
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println( getValue( Action.NAME ) + " selected." );
		}
	}
	
	public MenuFrame() {
		setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
		//File是一級選單
		JMenu fileMenu = new JMenu("File");
		//File下面的二級選單有:New, Open, Save, Save As, Exit
		fileMenu.add(new TestAction("New"));
		//給Open選單項新增快捷鍵
		JMenuItem openItem = fileMenu.add(new TestAction("Open"));
		openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 0"));
		//將一個分隔符行新增到File選單中
		fileMenu.addSeparator();
		//給Save選單項新增快捷鍵
		saveAction = new TestAction("Save");
		JMenuItem saveItem = fileMenu.add(saveAction);
		saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));
		//新增Save As選單項
		saveAsAction = new TestAction("Save As");
		fileMenu.add(saveAsAction);
		fileMenu.addSeparator();
		//新增Exit選單項
		fileMenu.add(new AbstractAction("Exit") {
			@Override
		public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		//==============================================
		
		//readonlyItem是複選框選單項
		readonlyItem = new JCheckBoxMenuItem( "Read-only" );
		readonlyItem.addActionListener(new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			//表示勾選了Read-only複選框,就不能點選Save或者Save As選單項了
			boolean saveOk = !readonlyItem.isSelected();
				saveAction.setEnabled(saveOk);
				saveAsAction.setEnabled(saveOk);
			}
		});
		//group是單選按鈕組;其中有Insert和Overtype兩個單選按鈕,即選了其中一個,另一個就會失選; 設定insert初始被選中
		ButtonGroup group = new ButtonGroup();
		JRadioButtonMenuItem isertItem = new JRadioButtonMenuItem("Insert");
		isertItem.setSelected(true);
		JRadioButtonMenuItem overtypeItem = new JRadioButtonMenuItem("Overtype");
		group.add(isertItem);
		group.add(overtypeItem);
		
		//Edit是一級選單項,下面包括了Cut, Copy, Paste, Options 4個二級選單項
		//Options是二級選單項,下面又包括readonlyItem,isertItem,overtypeItem3個三級選單項
		Action cutAction = new TestAction("Cut");
		cutAction.putValue(Action.SMALL_ICON, new ImageIcon("cut.gif"));
		Action copyAction = new TestAction("Copy");
		copyAction.putValue(Action.SMALL_ICON, new ImageIcon("copy.gif"));
		Action pasteAction = new TestAction("Paste");
		pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("paste.gif"));
		
		JMenu editMenu = new JMenu("Edit");
		editMenu.add(cutAction);
		editMenu.add(copyAction);
		editMenu.add(pasteAction);
		
		JMenu optionMenu = new JMenu("Options");
		optionMenu.add(readonlyItem);
		optionMenu.addSeparator();;
		optionMenu.add(isertItem);
		optionMenu.add(overtypeItem);
		
		editMenu.addSeparator();
		editMenu.add(optionMenu);
		
		//=============================================
		
		//Help是一級選單項,下面有Index, About兩個二級選單項
		JMenu helpMenu = new JMenu("Help");
		helpMenu.setMnemonic('H');//給H字母新增快捷鍵;可以ALT+H喚醒Help選單
		JMenuItem indexItem = new JMenuItem("Index");
		indexItem.setMnemonic('I');
		helpMenu.add(indexItem);
		Action aboutAction = new TestAction("About");
		//給字母A新增快捷鍵,即直接按A就能喚醒About選單項;前提是Help已經喚醒
		aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));
		helpMenu.add(aboutAction);
		
		//選單欄,將所有一級選單項放入其中
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		menuBar.add(fileMenu);
		menuBar.add(editMenu);
		menuBar.add(helpMenu);
		
		//彈出選單;/點選滑鼠右鍵,彈出選單
		popup = new JPopupMenu();
		popup.add(cutAction);
		popup.add(copyAction);
		popup.add(pasteAction);
		
		JPanel panel = new JPanel();
		//點選滑鼠右鍵,彈出選單
		panel.setComponentPopupMenu(popup);
		add(panel);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new MenuFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
	
}

6、工具欄

工具欄是在程式中提供的快速訪問常用命令的按鈕欄;工具欄可以隨處移動;

package comp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;

public class ToolBarFrame extends JFrame{
	private static final int DEFAULT_WIDTH = 300;
	private static final int DEFAULT_HEIGHT =200;
	private JPanel panel;
	
	public ToolBarFrame() {
		setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
		panel = new JPanel();
		add( panel, BorderLayout.CENTER );
		Action blueAction = new ColorAction( "Blue", new ImageIcon("blue-ball.gif"), Color.BLUE );
		Action yellowAction = new ColorAction( "Yellow", new ImageIcon("yellow-ball.gif"), Color.YELLOW );
		Action redAction = new ColorAction( "Red", new ImageIcon("yed-ball.gif"), Color.RED );
		Action exitAction = new AbstractAction( "Exit", new ImageIcon("exit.gif") ) {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		};
		exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit");
		
		JToolBar bar = new JToolBar();
		bar.add(blueAction);//返回的是一個按鈕,即相當於在工具欄中增加一個按鈕
		bar.add(yellowAction);
		bar.add(redAction);
		bar.addSeparator();
		bar.add(exitAction);
		add(bar,BorderLayout.NORTH);
		
		//將Action物件新增到選單欄中
		JMenu menu = new JMenu("Color");
		menu.add(yellowAction);
		menu.add(blueAction); 
		menu.add(redAction);
		menu.add(exitAction);
		JMenuBar menuBar = new JMenuBar();
		menuBar.add(menu);
		setJMenuBar(menuBar);
		
	}
	
	//動作
	class ColorAction extends AbstractAction{
		public ColorAction( String name, Icon icon, Color c ) {
			putValue(Action.NAME, name);
			putValue(Action.SMALL_ICON, icon);
			putValue(Action.SHORT_DESCRIPTION, name+" background");
			putValue("Color", c);
		}
		
		@Override
		public void actionPerformed(ActionEvent e) {
			Color c = (Color) getValue("Color");
			panel.setBackground(c);
		}
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new ToolBarFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
	
}

7、對話方塊

(1)模式對話方塊:在對話方塊關閉之前,應用程式不能繼續執行

(2)無模式對話方塊:比如工具欄

package comp;

import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class DialogFrame extends JFrame{
	private AboutDialog dialog;
	
	public DialogFrame() {
		setSize(300, 200);
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		
		JMenu fileMenu = new JMenu("File");
		menuBar.add(fileMenu);
		
		JMenuItem aboutItem = new JMenuItem("About");
		aboutItem.addActionListener(e -> {
			if(dialog == null) {
				dialog = new AboutDialog(DialogFrame.this);
			}
			dialog.setVisible(true);
		});
		fileMenu.add(aboutItem);
		
		JMenuItem exitItem = new JMenuItem("Exit");
		exitItem.addActionListener(e -> System.exit(0));
		fileMenu.add(exitItem);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new DialogFrame();//初始化視窗
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設定:關閉視窗,則程式退出
				frame.setVisible(true);//顯示視窗
			}
		});
	}
}

class AboutDialog extends Dialog{
	public AboutDialog(JFrame owner) {
		//構造一個對話方塊 owner表示對話方塊的擁有者,About DialogTest表示對話方塊的標題,true代表這是模式對話方塊
		super(owner, "About DialogTest", true);
		setSize(200, 200);
		add(new JLabel("<html><h1><i>Core java</i></h1><hr>By Cay Horstman</html>"	),BorderLayout.CENTER	);
		
		JButton ok = new JButton("ok");
		ok.addActionListener(event -> setVisible(false));
		
		JPanel panel = new JPanel();
		panel.add(ok);
		add(panel, BorderLayout.SOUTH);
	}
}