学习目标
n Swing组件特点
n 复选框(JCheckBox)
n 单选按钮(JRadioButton)
n 边界(Border)
n 组合框(JComboBox)
n 滑块(JSlider)
n 微调控制器(JSpinner)
n 文件对话框(JFileChooser)
n 颜色选择器(JColorChooser)
知识要点
Swing组件都有三个要素:
n 内容,例如,按钮的状态(是否按下)或者文本框中的文本。
n 外观显示(颜色,尺寸)。
n 行为(对事件的反应)。
也就是MVC模式:实现此模式的三个独立的类:
n 模型-------存储内容
n 视图-------显示内容
n 控制器----处理用户输入
这个模式明确规定了三个对象如何进行交互。模型存储内容,它没有任何用户界面。对于一个按钮来说,内容非常简单-它只是一组标志,用来说明按钮是否按下,是否启用等等。对于一个文本框来说,内容稍稍复杂,它是容纳当前文本的一个字符串对象。这个内容和视图的内容并不一致------如果内容的长度大于文本框的显示长度,那么用户看到的就只有文本框显示的那一部分。模型必须实现改变和发现内容的方法。例如:一个文本模型中的方法有:在当前文本中添加或者删除字符以及把当前文本作为一个字符串返回等。再次强调,模型是完全不可见的,显示存储在模型中的数据是视图的工作。
实例分析
例1
问题的描述:
复选框(JCheckBox)的使用
解决方案:
请看下例
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JCheckBoxTest {
public static void main(String[] args) {
// 实例化框架
JCheckBoxFrame f = new JCheckBoxFrame();
// 设置关闭事件---关闭框架,整个应用程序退出
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 显示框架
f.setVisible(true);
}
}
class JCheckBoxFrame extends JFrame {
// 用来显示数据的
private JLabel label;
// 用来控制粗体的复选按钮
private JCheckBox bold;
// 用来控制斜体的复选按钮
private JCheckBox italic;
// 字体的大小
public static final int FONTSIZE = 30;
public JCheckBoxFrame() {
// 设置框架的标题
setTitle("JCheckBoxFrame");
// 设置框架的大小
setSize(400, 300);
// 得到框架的内容窗格
Container contentPane = getContentPane();
// 初始化JLabel组件
label = new JLabel("The dog jumps over the pig");
// 设置JLabel组件显示的字体
label.setFont(new Font("Serif", Font.PLAIN, FONTSIZE));
// 内容窗格默认的是边框布局—把label组件放到内容窗格的中间
contentPane.add(label, BorderLayout.CENTER);
// 建立一个监听器对象
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
int mode = 0;
if (bold.isSelected())
mode += Font.BOLD;
if (italic.isSelected())
mode += Font.ITALIC;
label.setFont(new Font("Serif", mode, FONTSIZE));
}
};
// 创建一个面板,该面板是用来加两个复选框组件
JPanel buttonPanel = new JPanel();
// 创建一个复选框组件
bold = new JCheckBox("Bold");
// 给复选框加监听器对象
bold.addActionListener(listener);
// 把粗体复选框加到面板里
buttonPanel.add(bold);
italic = new JCheckBox("Italic");
italic.addActionListener(listener);
buttonPanel.add(italic);
// 把面板放到内容窗格的中间
contentPane.add(buttonPanel, BorderLayout.SOUTH);
}
}
编译,运行以及输出的结果为:
(如图1所示)
例2
问题的描述:
单选按钮(JRadioButton)的使用
解决方案:
对于复选框来说,用户可以选折0个或多个。在许多情况下,我们需要用户
只选择几个框中的一个。当用户选择另外一个时,前一个选择就自动取消。
这样的一组框通常称作一个单选按钮组(radio button group),这是因
为这些按钮的工作方式像收音机上的电台选择按钮,当按下一个按钮时,前
一个按下的按钮则自动释放。
请看下例:
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
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 JRadioButtonTest {
public static void main(String[] args) {
JRadioButtonFrame f = new JRadioButtonFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
class JRadioButtonFrame extends JFrame {
private JPanel buttonPanel;
private ButtonGroup group;
private JLabel label;
public static final int DEFAULT_SIZE = 30;
public JRadioButtonFrame() {
setTitle("JRadioButtonFrame");
setSize(400, 300);
Container contentPane = getContentPane();
label = new JLabel("The lazy dog doesn't jump overthe clever pig");
label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));
contentPane.add(label, BorderLayout.CENTER);
// 创建一个面板,该面板用来放单选按钮
buttonPanel = new JPanel();
// 建立一个按钮组,属于一个按钮组的按钮只能按下一个
group = new ButtonGroup();
// 下面用方法来完成功能,更符合面向对象的特点
addRadioButton("Small", 12);
addRadioButton("Medium", 18);
addRadioButton("Large", 25);
addRadioButton("Extra large", 36);
// 把按钮面板加到内容窗格的南边
contentPane.add(buttonPanel, BorderLayout.SOUTH);
}
// 方法中的内部类访问方法的参数,必须定义成final类型的
public void addRadioButton(String name, final int size) {
// ==运算优先级比=高,所以先计算size == DEFAULT_SIZE,
// 然后再把结果给selected变量
boolean selected = size == DEFAULT_SIZE;
// 创建一个JRadioButton实例
JRadioButton button = new JRadioButton(name, selected);
// 把该JRadioButton放到一个按钮组里
group.add(button);
// 再把该JRadioButton放到同一个面版里进行显示
buttonPanel.add(button);
// 创建单选按钮的监听器对象
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setFont(new Font("Serif", Font.PLAIN, size));
}
};
// 给单选按钮加监听器
button.addActionListener(listener);
}
}
运行结果如图2所示。
例3
问题的描述:
边界的使用
解决方案:
如果在一个窗口中有多组单选按钮,那么你需要从视觉上说明哪些按钮属于
同一组。Swing提供了一组有用的边界来解决该问题。你可以为任何扩展了
JComponent的组件提供一种边界。最常见的用法是在一个面板周围设置一
种边界,然后用其他用户界面元素(如单选按钮)来填充该面板。
有几种不同边界可供选择,但是使用它们的步骤完全一样:
n 低斜面
n 凸斜面
n 蚀刻
n 直线
n 不光滑
n 空(只是在组件周围创建一些空白地方)
请看下例:
package com.swing;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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 BorderTest {
public static void main(String[] args) {
BorderFrame f = new BorderFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class BorderFrame extends JFrame {
private JPanel demoPanel;
private JPanel buttonPanel;
private ButtonGroup group;
public BorderFrame()
{
setTitle("BorderTest");
setSize(400,300);
demoPanel = new JPanel();
buttonPanel = new JPanel();
group = new ButtonGroup();
// 通过方法来完成加按钮和给按钮事件的操作
addRadioButton("Loweredbevel",BorderFactory.createLoweredBevelBorder());
addRadioButton("Raised
bevel",BorderFactory.createRaisedBevelBorder());
addRadioButton("Etched",BorderFactory.createEtchedBorder());
addRadioButton("Line",BorderFactory.createLineBorder(Color.blue));
addRadioButton("Matte",BorderFactory.createMatteBorder(10,10,10,10,Color.blue));
addRadioButton("Empty",BorderFactory.createEmptyBorder());
// 创建一个边框
Border etched =
BorderFactory.createEtchedBorder();
// 在上一个边框的基础上又加了标题(两个边框)
Border titled = BorderFactory.createTitledBorder(etched,"Border types");
// 设置面板的边框
buttonPanel.setBorder(titled);
Container contentPane = getContentPane();
// 设置内容窗格的布局为两行一列
contentPane.setLayout(new GridLayout(2,1));
contentPane.add(buttonPanel);
contentPane.add(demoPanel);
}
// 方法中的内部类访问方法的参数,必须是final类型的
public void addRadioButton(String buttonName, final Border b) {
JRadioButton button = new JRadioButton(buttonName);
// 给单选按钮加监听器
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
demoPanel.setBorder(b);
// 使当前窗口生效
validate();
}
});
// 把按钮放到按钮组里
group.add(button);
// 把按钮放到面板里
buttonPanel.add(button);
}
}
编译和运行的结果为:
(如图 3 所示)
例4
问题的描述:
组合框(JComboBox)的用法
解决方案:
如果你有很多的选择项,那么使用单选按钮就不合适了,这是因为它们会占
用很大的屏幕空间。取而代之的是,你可以使用一个组合框。当用户点击该
组件时,一列选择项就会下拉弹出,然后用户可以选择其中的一个。如果该
下拉列表框被设置成可编辑的,那么你可以编辑当前选择项,这时候该组件
才称作组合框----它把编辑框的灵活性与一组预定义的选择项组合起来。
JComboBox类提供了组
合框组件。
请看下例:
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JComboBoxTest {
public static void main(String[] args) {
JComboBoxFrame f = new JComboBoxFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class JComboBoxFrame extends JFrame {
private JComboBox faceCombo;
private JLabel label;
public static final int DEFAULT_SIZE = 30;
public JComboBoxFrame() {
setTitle("JComboBoxFrame");
setSize(400, 300);
Container contentPane = getContentPane();
label = new JLabel("The dog jumps over the monkey");
label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));
contentPane.add(label, BorderLayout.CENTER);
// 创建JComboBox组件,该组件采用了MVC模式
faceCombo = new JComboBox();
// 设置该组件为可编辑方式
faceCombo.setEditable(true);
// 给该组件放数据,表面上看是放到该组件里,
// 实际上是放到该组件对应的模型里,查看JComboBox源代码
faceCombo.addItem("Serif");
faceCombo.addItem("SansSerif");
faceCombo.addItem("Monospaced");
faceCombo.addItem("Dialog");
faceCombo.addItem("DialogInput");
// 给JComboBox加事件
faceCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setFont(new Font((String) faceCombo.getSelectedItem(),
Font.PLAIN, DEFAULT_SIZE));
}
});
JPanel comboPanel = new JPanel();
comboPanel.add(faceCombo);
contentPane.add(comboPanel, BorderLayout.SOUTH);
}
}
运用模型实现的方式:
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JComboBoxModel {
public static void main(String[] args) {
JComboBoxModelFrame f = newJComboBoxModelFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class JComboBoxModelFrame extends JFrame {
private JComboBox faceCombo;
private JLabel label;
public static final int DEFAULT_SIZE = 30;
public JComboBoxModelFrame() {
setTitle("JComboBoxFrame");
setSize(400, 300);
Container contentPane = getContentPane();
label = new JLabel("The dogjumps over the monkey");
label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));
contentPane.add(label, BorderLayout.CENTER);
// 创建JComboBoxModel
DefaultComboBoxModel comboModel = newDefaultComboBoxModel();
comboModel.addElement("Serif");
comboModel.addElement("SansSerif");
comboModel.addElement("Monospaced");
comboModel.addElement("Dialog");
comboModel.addElement("DialogInput");
// 创建JComboBox组件,该组件采用了MVC模式
faceCombo = new JComboBox(comboModel);
// 设置该组件为可编辑方式
faceCombo.setEditable(true);
// 给JComboBox加事件
faceCombo.addActionListener(newActionListener() {
public void actionPerformed(ActionEvent e) {
label.setFont(new Font((String) faceCombo.getSelectedItem(),
Font.PLAIN, DEFAULT_SIZE));
}
});
JPanel comboPanel = new JPanel();
comboPanel.add(faceCombo);
contentPane.add(comboPanel, BorderLayout.SOUTH);
}
}
运行的结果如图4所示。
例5
问题的描述:
滑块(JSlider)的使用(用到了model的设计)
解决方案:
组合框允许用户从一组离散值中进行选择。而滑块允许进行连续值的选择,
例如,选择从1到100的任意值。构造一个滑块的方法如下:
JSliderslider=new JSlider(min,max,initialValue);
如果你忽略最小值,最大值和初始值,那么这三项分别默认为0,100,50。
或者,如果你需要一个垂直的滑块,那么可以使用如下构造器:
JSliderslider = new
JSlider(SwingConstants.VERTICAL,min,max,initialValue);
请看下例:
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
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.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JSliderTest {
public static void main(String[] args) {
JSliderTestFrame f = new JSliderTestFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class JSliderTestFrame extends JFrame {
private JPanel sliderPanel;
private JTextField textField;
private ChangeListener listener;
public JSliderTestFrame() {
setTitle("JSliderTest");
setSize(400, 500);
sliderPanel = new JPanel();
sliderPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
// 给滑块定义的监听器
listener = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
// 得到事件源
JSlider source = (JSlider) e.getSource();
// 让textField显示当前滑块里的值
textField.setText("" + source.getValue());
}
};
// 加一个 plain slider
JSlider slider = new JSlider();
addSlider(slider, "Plain");
S // 加一个有刻度值的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Ticks");
// 加一个有刻度值的并且不能选择刻度之间的值的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setSnapToTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Snapto ticks");
// 加一个填充的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.putClientProperty("JSlider.isFilled", Boolean.TRUE);
addSlider(slider, "Filled");
// 加一个反向填充的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.putClientProperty("JSlider.isFilled", Boolean.TRUE);
slider.setInverted(true);
addSlider(slider, "Inverted");
// 加一个有刻度值的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
addSlider(slider, "Labels");
// 加一个有刻度值为A,B,C,D,E,F的 slider
slider = new JSlider();
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
Hashtable labelTable = new Hashtable();
// 加对应的字母
labelTable.put(new Integer(0), new JLabel("A"));
labelTable.put(new Integer(20), new JLabel("B"));
labelTable.put(new Integer(40), new JLabel("C"));
labelTable.put(new Integer(60), new JLabel("D"));
labelTable.put(new Integer(80), new JLabel("E"));
labelTable.put(new Integer(100), new JLabel("F"));
slider.setLabelTable(labelTable);
addSlider(slider, "Customlabels");
// 加一个有刻度图标的 slider
slider = new JSlider();
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setSnapToTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(20);
labelTable = new Hashtable();
// 加对应的图片
labelTable.put(new Integer(0), new JLabel(new ImageIcon("01.gif")));
labelTable.put(new Integer(20), new JLabel(new ImageIcon("02.gif")));
labelTable.put(new Integer(40), new JLabel(new ImageIcon("03.gif")));
labelTable.put(new Integer(60), new JLabel(new ImageIcon("04.gif")));
labelTable.put(new Integer(80), new JLabel(new ImageIcon("05.gif")));
labelTable.put(new Integer(100), new JLabel(new ImageIcon("06.gif")));
slider.setLabelTable(labelTable);
addSlider(slider, "Iconlabels");
// 加一个textField 用来显示滑块里的值
textField = new JTextField();
Container contentPane = getContentPane();
contentPane.add(sliderPanel, BorderLayout.CENTER);
contentPane.add(textField, BorderLayout.SOUTH);
}
// 加JSlider的方法,并且给JSlider加事件等操作
public void addSlider(JSlider s, String description) {
// 给滑块加监听器
s.addChangeListener(listener);
// 创建一个面板,用来加滑块和label
JPanel panel = new JPanel();
panel.add(s);
panel.add(new JLabel(description));
// 把滑块面板加的大的面板里显示
sliderPanel.add(panel);
}
}
运行的结果如图5。
例6
问题的描述:
微调控制器(JSpinner)的使用(用到了model的设计)
解决方案:
JSpinner(微调控制器)也是文本框,它在一边带有两个小按钮,可以让你
增加或者减少存
请看下例:
package com.swing;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.AbstractSpinnerModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
public class JSpinnerTest {
public static void main(String[] args) {
JSpinnerFrame f = new JSpinnerFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class JSpinnerFrame extends JFrame {
private JPanel mainPanel;
private JButton okButton;
public JSpinnerFrame() {
setTitle("SpinnerTest");
setSize(400, 300);
Container contentPane = getContentPane();
JPanel buttonPanel = new JPanel();
okButton = new JButton("Ok");
buttonPanel.add(okButton);
contentPane.add(buttonPanel, BorderLayout.SOUTH);
mainPanel = new JPanel();
// 设置该面板的布局方式为网格布局,多行3列,0表示多行
mainPanel.setLayout(new GridLayout(0, 3));
contentPane.add(mainPanel, BorderLayout.CENTER);
// 创建一个JSpinner
JSpinner defaultSpinner = new JSpinner();
// 通过方法把JSpinner加到mainPanel里
addRow("Default", defaultSpinner);
// 创建一个给定model的JSpinner对象,模型里的数据为0,0.5,1,1.5,,,,10
JSpinner boundedSpinner = new JSpinner(new SpinnerNumberModel(5, 0, 10,
0.5));
addRow("Bounded", boundedSpinner);
// 取出当前操作系统里,所有存在的字体
String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
// 创建给定model的JSpinner对象,模型里的数据是字体名字
JSpinner listSpinner = new JSpinner(new SpinnerListModel(fonts));
addRow("List", listSpinner);
// 通过匿名模型类对象,创建JSpinner对象
JSpinner reverseListSpinner = new JSpinner(new SpinnerListModel(fonts) {
// 改变模型取数据,取下一个数据,给的是上一个数据,和上个模型相反
public Object getNextValue() {
return super.getPreviousValue();
}
public Object getPreviousValue() {
return super.getNextValue();
}
});
addRow("ReverseList", reverseListSpinner);
// 通过日期模型来创建JSpinner对象
JSpinner dateSpinner = new JSpinner(new SpinnerDateModel());
addRow("Date", dateSpinner);
JSpinner betterDateSpinner = new JSpinner(new SpinnerDateModel());
// 得到日期格式
String pattern = ((SimpleDateFormat) DateFormat.getDateInstance())
.toPattern();
// 创建编辑方式和显示日期的格式
betterDateSpinner.setEditor(new JSpinner.DateEditor(betterDateSpinner,
pattern));
addRow("BetterDate", betterDateSpinner);
JSpinner timeSpinner = new JSpinner(new SpinnerDateModel(
new GregorianCalendar(2000, Calendar.JANUARY, 1, 12, 0, 0)
.getTime(), null, null, Calendar.HOUR));
addRow("Time", timeSpinner);
}
public void addRow(String labelText, final JSpinner spinner) {
// 加label
mainPanel.add(new JLabel(labelText));
// 加 spinner
mainPanel.add(spinner);
final JLabel valueLabel = new JLabel();
// 加值的label
mainPanel.add(valueLabel);
// 按钮事件
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object value = spinner.getValue();
valueLabel.setText(value.toString());
}
});
}
}
运行的结果如图6。
例7
问题的描述:
文件对话框(JFileChooser)的使用
解决方案:
当你编写一个应用程序时,你常常需要打开和保存文件。一个好的文件对话
框是很难编写的,它应该能够显示文件和目录并且让用户浏览文件系统。你
肯定不会想去发明这种对话框。幸运的是,Swing提供一个JFileChooser
类可以用来显示一个文件对话框;
请看下例:
package com.swing;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileView;
//主类
public class JFileChooserTest {
public static void main(String[] args) {
ImageViewerFrame f = new ImageViewerFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
// 框架类
class ImageViewerFrame extends JFrame {
private JLabel label;
private JFileChooser chooser;
public ImageViewerFrame() {
setTitle("JFileChooserTest");
setSize(500, 400);
// 创建一个菜单栏
JMenuBar menuBar = new JMenuBar();
// 给框架加菜单栏
setJMenuBar(menuBar);
// 创建一个名字为File的菜单
JMenu menu = new JMenu("File");
// 把File菜单加到菜单栏里
menuBar.add(menu);
// 创建一个菜单项Open
JMenuItem openItem = new JMenuItem("Open");
// 把菜单项放到File菜单里
menu.add(openItem);
// 给Open菜单项加动作监听器事件
openItem.addActionListener(new FileOpenListener());
// 创建一个菜单项Exit
JMenuItem exitItem = new JMenuItem("Exit");
// 把菜单项放到菜单File里
menu.add(exitItem);
// 给Exit菜单项加动作监听器事件
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 整个应用程序退出
System.exit(0);
}
});
// 创建一个label组件,用来放用户选择的图片
label = new JLabel();
// 得到内容窗格
Container c = getContentPane();
// 把label组件放到(默认)内容窗格的中间
c.add(label);
// 创建个文件选择器对象
chooser = new JFileChooser();
// 创建一个文件过滤器对象
final ExtensionFileFilter filter = new ExtensionFileFilter();
filter.addExtension("jpg");
filter.addExtension("jpeg");
filter.addExtension("gif");
filter.setDescription("Imagefiles");
// 给文件选择器加过滤器
chooser.setFileFilter(filter);
// 给文件选择器加预览器
chooser.setAccessory(new ImagePreviewer(chooser));
// 给文件选择器加文件夹的预览图标
chooser.setFileView(new FileIconView(filter, new ImageIcon("02.gif")));
}
// 内部类----动作监听器,是给Open菜单选项加的
private class FileOpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// 设置文件选择器的目录为当前目录
chooser.setCurrentDirectory(new File("."));
// 显示文件打开对话框
int result = chooser.showOpenDialog(ImageViewerFrame.this);
// 如果选择图片,那么在label里进行显示
if (result == JFileChooser.APPROVE_OPTION) {
String name = chooser.getSelectedFile().getPath();
label.setIcon(new ImageIcon(name));
}
}
};
};
// 文件过滤器
class ExtensionFileFilter extends FileFilter {
private String description = "";
// 用来保存文件的后缀
private ArrayList extensions = new ArrayList();
// 加文件后缀的方法
public void addExtension(String extension) {
if (!extension.startsWith("."))
extension = "." + extension;
extensions.add(extension.toLowerCase());
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
// 选择文件
public boolean accept(File f) {
// 如果选的是目录,那么文件无效
if (f.isDirectory())
return false;
String name = f.getName().toLowerCase();
// 如果文件的后缀是指定的文件后缀(图片文件),那么图片有效
for (int i = 0; i < extensions.size(); i++)
if (name.endsWith((String) extensions.get(i)))
return true;
// 如果执行下面的语句,说明是无效的文件
return false;
}
};
// 文件图标的显示
class FileIconView extends FileView {
private FileFilter filter;
private Icon icon;
public FileIconView(FileFilter filter, Icon icon) {
this.filter = filter;
this.icon = icon;
}
public Icon getIcon(File f) {
// 如果文件是过滤器可以接受的文件,那么返回图标
if (!f.isDirectory() && filter.accept(f))
return icon;
else
return null;
}
};
// 文件的预览类
class ImagePreviewer extends JLabel {
public ImagePreviewer(JFileChooser chooser) {
// 设置预览区的大小
setPreferredSize(new Dimension(100, 100));
// 设置边框
setBorder(BorderFactory.createEtchedBorder());
// 给文件选择器加属性改变监听器,也就是选择一个图片就能预览
chooser.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if (e.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) {
File f = (File) (e.getNewValue());
if (f != null && f.isFile()) {
ImageIcon icon = new ImageIcon(f.getPath());
if (icon.getIconWidth() > getWidth())
// 得到按比例缩小的图片
icon = new ImageIcon(icon.getImage()
.getScaledInstance(getWidth(), -1,
Image.SCALE_DEFAULT));
// 在预览区设置图片预览
setIcon(icon);
}
}
}
});
}
}
运行结果如图7,8
例8
问题的描述:
颜色选择器(JColorChooser)的使用
解决方案:
上个例子你已经看到,高质量的文件选择器是一个很复杂的用户界面组件,
你可能不愿意自己实现。除了文件选择器之外,Swing只提供了另外一种选
择器-----JColorChooser。你可以使用它来挑选一种颜色。同
JFileChooser类一样,颜色选择器是一个组件而非一个对话框。但是它包
含了用于创建包含一个颜色选择器组件的对话框的方法。
请看下例:
package com.swing;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JColorChooserTest {
public static void main(String[] args) {
JColorChooserFrame f = new JColorChooserFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
class JColorChooserFrame extends JFrame {
public JColorChooserFrame() {
setTitle("JColorChooserTest");
setSize(400, 300);
// 创建一个面板
ColorChooserPanel panel = new ColorChooserPanel();
Container contentPane = getContentPane();
contentPane.add(panel);
}
};
// 颜色选择器的按钮面板
class ColorChooserPanel extends JPanel {
public ColorChooserPanel() {
JButton modalButton = new JButton("Modal");
modalButton.addActionListener(new ModalListener());
add(modalButton);
JButton modelessButton = new JButton("Modeless");
modelessButton.addActionListener(new ModelessListener());
add(modelessButton);
JButton immediateButton = new JButton("Immediate");
immediateButton.addActionListener(new ImmediateListener());
add(immediateButton);
}
// 内部类来实现
private class ModalListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Color defaultColor = getBackground();
// 创建颜色选择器,返回值为选种的颜色
Color selected = JColorChooser.showDialog(ColorChooserPanel.this,
"Set background", defaultColor);
// ColorChooserPanel类从 JPanel类继承过来的方法
setBackground(selected);
}
};
// 内部类---该内部类的功能和上面的监听器一样
private class ModelessListener implements ActionListener {
private JDialog dialog;
private JColorChooser chooser;
public ModelessListener() {
// 创建个颜色选择器对象
chooser = new JColorChooser();
// 在产生对话框的时候,直接加了动作监听器
dialog = JColorChooser.createDialog(ColorChooserPanel.this,
"BackgroundColor", false, chooser, new ActionListener() {
public void actionPerformed(ActionEvent e) {
setBackground(chooser.getColor());
}
}, null);
}
public void actionPerformed(ActionEvent e) {
// 设置颜色选择器的颜色为当前面板的颜色
chooser.setColor(getBackground());
dialog.setVisible(true);
}
}
// 内部类----实现了即时改变面板的颜色
private class ImmediateListener implements ActionListener {
private JDialog dialog;
private JColorChooser chooser;
public ImmediateListener() {
chooser = new JColorChooser();
// 给颜色选择器加了改变监听器:颜色一选择 ,面板马上变为选择的颜色
chooser.getSelectionModel().addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
setBackground(chooser.getColor());
}
});
dialog = new JDialog((JFrame) null, false/* not moal */);
dialog.getContentPane().add(chooser);
dialog.pack();
}
public void actionPerformed(ActionEvent e) {
// 设置颜色选择器的颜色为当前面板的颜色
chooser.setColor(getBackground());
dialog.setVisible(true);
}
};
}
运行的结果如图9
内容总结
对Swing组件有一定的了解,会对组件进行MVC的设计
独立实践
1,做一个综合的界面,尽量用到上面最多的组件。
2,做一个组合框,设计该组件的model部分