第11章 进度条、滑杆和分隔条
本章介绍三个Swing组件:JProgressBar、JSlider和JSeparator。 人们经常用进度条反映耗时任务已完成的百分比,本章将提供这样一个例子。但是,用ProgressMonitor和ProgressMonitorInputStream实用工具来反映一个任务的进度信息通常会更容易。“进度监控”小节中讨论了ProgressMonitor和ProgressMonitorInputStream实用工具。 JProgressBar和JSlider与JSeparator一样,用来描述一个介于最小值和最大值之间的值。因此,与JProgressBar和JSlider相关的模型是BoundedRangeModel接口的一个实现。 JSeparator是绘制一条蚀刻线的组件,它把逻辑上相关的组件分隔在一组,JSeparator组件可水平地垂直地放置。
11.1 JProgressBar
JProgressBar是一个简单的组件,它一般是一种颜色部分或完全填充的矩形。缺省情况下,进度条配备了一个凹陷的边框,并水平放置。 进度条还可以选择显示一个字符串,这个字符串在进度条矩形的中央位置上显示。这个字符串缺省时为耗时任务已完成的百分比。这个字符串可用JProgressBar.setString方法定制。 图11-1中示出的小应用程序创建了不同配置的进度条。 例11-1列出了图11-1中示出的小应用程序的代码。
例11-1 各种配置的进度条
import javax.swing.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private JProgressBar[] progressBars = { new JProgressBar(), new JProgressBar(), new JProgressBar(), new JProgressBar() };
public void init() { Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
for(int i=0; i < progressBars.length; ++i) { JProgressBar pb = progressBars[i];
if(i == 0) { pb.setStringPainted(true); pb.setString("Custom String"); } if(i == 1) { pb.setOrientation(JProgressBar.VERTICAL); pb.setForeground(Color.yellow); pb.setMaximum(1000); pb.setValue(50); pb.setBorder( BorderFactory.createRaisedBevelBorder()); } if(i == 2) { pb.setForeground(Color.blue); pb.setBorderPainted(false); pb.setValue(50); pb.setStringPainted(true); } if(i == 3) { pb.setOrientation(JProgressBar.VERTICAL); pb.setForeground(Color.red); pb.setValue(90); pb.setStringPainted(true); pb.setBorder( BorderFactory.createEtchedBorder()); } contentPane.add(pb); } } }
这个小应用程序创建了一组进度条,并为每个进度条设置了各种不同的属性,从而产生了图11-1中示出的各种不同配置。
11.1.1进度条与线程
例11-2 使用JProgressBar
import javax.swing.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private JProgressBar progressBar = new JProgressBar(); private JButton startButton = new JButton("start");
public void init() { Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(startButton); contentPane.add(progressBar);
progressBar.setStringPainted(true);
startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { (new UpdateThread()).start(); } }); } class UpdateThread extends Thread { Runnable update, finish; int value, min, max, increment;
public UpdateThread() { max = progressBar.getMaximum(); min = progressBar.getMinimum();
update = new Runnable() { public void run() { value = progressBar.getValue() + increment; updateProgressBar(value); } }; finish = new Runnable() { public void run() { updateProgressBar(min); } }; } public void run() { startButton.setEnabled(false);
while(value + increment <= max) { simulateTimeConsumingActivity(); SwingUtilities.invokeLater(update); } SwingUtilities.invokeLater(finish); startButton.setEnabled(true); } private void updateProgressBar(int value) { progressBar.setValue(value); } private void simulateTimeConsumingActivity() { try { Thread.currentThread().sleep(1000); increment = (max - min) / 10; } catch(InterruptedException e) { e.printStackTrace(); } } } }
11.1.2 JProgressBar属性
11.1.3 JProgressBar事件
例11-3 监视一个进度条的值
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private JProgressBar pb = new JProgressBar();
public void init() { Container contentPane = getContentPane(); final JButton startButton = new JButton("start");
contentPane.setLayout(new FlowLayout()); contentPane.add(startButton); contentPane.add(pb);
startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { (new GetInfoThread(pb)).start(); } }); pb.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int min = pb.getMinimum(), max = pb.getMaximum(); int value = pb.getValue();
showStatus("Min: " + min + ", Max: " + max + ", Value: " + value); } }); } } class GetInfoThread extends Thread { Runnable update, finish; JProgressBar pb; int value, min, max, increment;
public GetInfoThread(JProgressBar progressBar) { pb = progressBar;
max = pb.getMaximum(); min = pb.getMinimum();
update = new Runnable() { public void run() { value = pb.getValue() + increment; pb.setValue(value); } }; finish = new Runnable() { public void run() { value = min; pb.setValue(value); } }; } public void run() { while(value + increment <= max) { simulateTimeConsumingActivity(); SwingUtilities.invokeLater(update); } SwingUtilities.invokeLater(finish); } private void simulateTimeConsumingActivity() { try { Thread.currentThread().sleep(1000); increment = (max - min) / 10; } catch(InterruptedException e) { e.printStackTrace(); } } }
11.1.4 JProgressBar类总结
11.1.5 AWT兼容
11.2 JSlider
例11-4 一个简单的JSlider例子
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*;
public class Test extends JApplet { public void init() { Container contentPane = getContentPane(); JSlider slider = new JSlider();
contentPane.add(slider, BorderLayout.NORTH); } }
11.2.1填充的滑杆
例11-5 一个填充的滑杆
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); JSlider slider = new JSlider();
slider.putClientProperty("JSlider.isFilled",Boolean.TRUE);
contentPane.add(slider, BorderLayout.NORTH); } }
11.2.2滑杆间隔标记
例11-6 显示滑杆的间隔标记
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*;
public class Test extends JApplet { public void init() { Container contentPane = getContentPane(); JSlider slider = new JSlider(); JPanel controlPanel = new ControlPanel(slider);
contentPane.setLayout(new BorderLayout(0,40)); contentPane.add(controlPanel, BorderLayout.NORTH); contentPane.add(slider, BorderLayout.CENTER); } class ControlPanel extends JPanel { public ControlPanel(final JSlider slider) { JCheckBox paintTicks = new JCheckBox("Paint Ticks"); JComboBox minorSpacing = new JComboBox(), majorSpacing = new JComboBox();
minorSpacing.addItem("0"); minorSpacing.addItem("3"); minorSpacing.addItem("5"); minorSpacing.addItem("10"); minorSpacing.addItem("20");
majorSpacing.addItem("0"); majorSpacing.addItem("3"); majorSpacing.addItem("5"); majorSpacing.addItem("10"); majorSpacing.addItem("20");
add(paintTicks); add(new JLabel("Minor Tick Spacing:")); add(minorSpacing); add(new JLabel("Major Tick Spacing:")); add(majorSpacing);
paintTicks.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JCheckBox cb = (JCheckBox)e.getSource(); slider.setPaintTicks(cb.isSelected()); slider.repaint(); } }); minorSpacing.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JComboBox cb = (JComboBox)e.getSource(); int spacing = Integer.parseInt( (String)cb.getSelectedItem());
slider.setMinorTickSpacing(spacing); slider.revalidate(); } }); majorSpacing.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JComboBox cb = (JComboBox)e.getSource(); int spacing = Integer.parseInt( (String)cb.getSelectedItem());
slider.setMajorTickSpacing(spacing); slider.revalidate(); } }); } } }
11.2.3滑杆标签
例11-7 显示缺省的JSlider标签
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); JSlider slider = new JSlider();
slider.setPaintLabels(true); slider.setMajorTickSpacing(20); contentPane.add(slider, BorderLayout.NORTH); } }
例11-8 定制滑杆标签
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); JSlider slider = new JSlider(); Icon[] icons = { new ImageIcon("basketball.gif"), new ImageIcon("baseball.gif"), new ImageIcon("soccer.gif"), new ImageIcon("clipboard.gif"), new ImageIcon("filmstrip.gif"), new ImageIcon("crab.gif"), }; Hashtable table = new Hashtable();
for(int i=0, loc=0; i < icons.length; i++, loc += 20) { table.put(new Integer(loc), new JLabel(Integer.toString(loc), icons[i], JLabel.LEFT)); }
slider.setLabelTable(table); slider.setPaintLabels(true); slider.setMajorTickSpacing(20);
contentPane.add(slider, BorderLayout.NORTH); } }
11.2.4反转滑杆值
例11-9 中列出图11-10中示出的小应用程序的代码
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { private JCheckBox checkBox = new JCheckBox("Invert"); private JSlider[] sliders = { new JSlider(), new JSlider(JSlider.VERTICAL) };
public Test() { Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(checkBox);
for(int i=0; i < sliders.length; ++i) { sliders[i].setPaintLabels(true); sliders[i].setMajorTickSpacing(20); contentPane.add(sliders[i]); }
checkBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for(int i=0; i < sliders.length; ++i) sliders[i].setInverted(checkBox.isSelected()); } }); } }
11.2.5滑杆的外延值
例11-10 设置一个滑杆的外延值
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); JSlider slider = new JSlider(); JPanel controlPanel = new ControlPanel(slider);
contentPane.add(controlPanel, BorderLayout.NORTH); contentPane.add(slider, BorderLayout.SOUTH);
slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider s = (JSlider)e.getSource(); showStatus("Min: " + s.getMinimum() + ", Max: " + s.getMaximum() + ", Extent: " + s.getExtent() + ", Value: " + s.getValue()); } }); } } class ControlPanel extends JPanel { public ControlPanel(final JSlider slider) { JComboBox extent = new JComboBox();
extent.addItem("0"); extent.addItem("10"); extent.addItem("20"); extent.addItem("30"); extent.addItem("40");
add(new JLabel("Extent:")); add(extent);
extent.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { JComboBox cb = (JComboBox)e.getSource(); int ext = Integer.parseInt( (String)cb.getSelectedItem());
slider.setExtent(ext); slider.revalidate(); } }); } }
11.2.6 JSlider属性
11.2.7 JSlider事件
例11-11 监视一个滑杆的值
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); JSlider slider = new JSlider();
contentPane.add(slider, BorderLayout.NORTH);
slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider s = (JSlider)e.getSource(); showStatus("Min: " + s.getMinimum() + ", Max: " + s.getMaximum() + ", Extent: " + s.getExtent() + ", Value: " + s.getValue() + ", Value Is Adjusting: " + s.getValueIsAdjusting()); } }); } }
11.2.8 JSlider类总结
11.2.9 AWT兼容
11.3 JSeparator
例11-12 一个不可见的分隔条
import java.awt.*; import javax.swing.*;
public class Test extends JApplet { public void init() { Container contentPane = getContentPane(); JSeparator s = new JSeparator(JSeparator.VERTICAL);
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("left")); contentPane.add(s); contentPane.add(new JButton("right")); } }
例11-13 控制分隔条的大小
import java.awt.*; import javax.swing.*;
public class Test extends JApplet { public void init() { Container contentPane = getContentPane(); JSeparator s = new JSeparator(JSeparator.VERTICAL); Dimension ps = s.getPreferredSize();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("left")); contentPane.add(s); contentPane.add(new JButton("right"));
s.setPreferredSize(new Dimension(ps.width, 50)); } }
例11-14 监控分隔条的大小
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet {
public void init() { Container contentPane = getContentPane(); final JSeparator s = new JSeparator(JSeparator.VERTICAL); final Dimension ps = s.getPreferredSize();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("left")); contentPane.add(s); contentPane.add(new JButton("right"));
addComponentListener(new ComponentAdapter() { public void componentShown(ComponentEvent e) { System.out.println("shown"); adjustSeparatorPreferredSize(); } public void componentResized(ComponentEvent e) { System.out.println("resized"); adjustSeparatorPreferredSize(); } private void adjustSeparatorPreferredSize() { s.setPreferredSize(new Dimension(ps.width, getSize().height)); s.revalidate(); } }); } }
11.3.1分隔条与框
例11-15 分隔条与框
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { private JPanel left, rightTop, rightBottom;
private Box box = new Box(BoxLayout.X_AXIS), rightBox = new Box(BoxLayout.Y_AXIS);
private JSeparator vs, hs; // vs = vertical separator // hs = horizontal separator public void init() { createBoxes(); setPanelBorders(); //setSeparatorPreferredSizes();
left.setPreferredSize(new Dimension(150,0));
getContentPane().add(box, BorderLayout.CENTER); } private void createBoxes() {
Component vStrut = box.createVerticalStrut(10), hStrut = box.createHorizontalStrut(10);
rightBox.add(rightTop = new JPanel()); rightBox.add(box.createVerticalStrut(10)); rightBox.add(hs = new JSeparator()); rightBox.add(box.createVerticalStrut(10)); rightBox.add(rightBottom = new JPanel());
box.add(left = new JPanel()); box.add(box.createHorizontalStrut(10)); box.add(vs = new JSeparator(JSeparator.VERTICAL)); box.add(box.createHorizontalStrut(10)); box.add(rightBox); } private void setSeparatorPreferredSizes() { vs.setMaximumSize( new Dimension(vs.getPreferredSize().width, Integer.MAX_VALUE));
hs.setMaximumSize( new Dimension(Integer.MAX_VALUE, hs.getPreferredSize().height)); } private void setPanelBorders() { left.setBorder( BorderFactory.createTitledBorder("Left")); rightTop.setBorder( BorderFactory.createTitledBorder("Right Top")); rightBottom.setBorder( BorderFactory.createTitledBorder("Right Bottom")); } }
11.3.2 JSeparator属性
略
11.3.3 JSeparator事件
略
11.3.4 AWT兼容
略