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);
	}
}

猜你喜欢

转载自blog.csdn.net/Carl_changxin/article/details/82978256