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