第4章 JComponent类
JComponent类是所有Swing轻量组件的基类,因此,我们单独用一章对它进行讨论。JComponent对Swing的意义就如同java.awt.Component对AWT的意义一样,它们都是它们各自框架组件的基类。
作为所有Swing轻量组件的基类,JComponent提供了大量的基本功能。要全面了解Swing,就必须知道JComponent类提供的功能,还必须知道如何使用JComponent类。
4.1 JComponent类概览
JComponent扩展java.awt.Container,而java.awt.Container又扩展java.awt.Component,因此,所有的Swing组件都是AWT容器。Component和Container类本身提供了大量的功能,因此,JComponent继承了大量的功能。本章(实际上本书)假设读者有AWT组件和容器的基本知识,这些基本知识在《Java2图形设计,卷Ⅰ:AWT》中用了大量的篇幅来介绍。
因为JComponent为几乎所有的Swing组件提供下层构件,因此,它是一个很大的类,包括100多个public方法。JComponent为它的扩展提供了下面的功能:
■边框。 ■自动滚动。
■可访问性。 ■工具提示。
■双缓存。 ■键击处理。
■调试图形。 ■客户属性。
4.1.1边框
任何JComponent的扩展都可以带边框。Swing提供了许多不同风格的边框,如雕刻边框、带标题边框和蚀刻边框。虽然一个组件只能有一个边框,但是边框是可以组合的。因此,从效果上来看,单个组件可有多个边框。图4-1示出了组合边框、带标题边框和定制边框。
边框通常用来组织组件集,但在其他情况下也是很有用的。例如,图4-1示出的组合框可以作为一显示艺术品略图的图形程序的图片帧。通常,可操作的边框在绘图程序中用来移动和改变对象的大小,而且作为Swing的定制边框,这种边框实现起来也很容易。
本章不详细介绍边框,有关边框的知识,请参见第5章“边框、图标和动作”。
4.1.2可访问性
可访问性是使人人都能使用软件。例如,为视力不好的用户放大字体或为听力不好的用户显示带声音的标题。
Swing的插入式界面模式体系结构通过允许把可选择的界面样式分配给一组组件来支持可访问性。图4-2所示的SwingSet样例应用程序使用一个定制的界面样式,它具有高反差、大字体的外观,为视力不好的用户提供了更好的可读性。
除了Swing插入式界面模式外,使用一个可访问API和一组可访问工具也能支持可访问性。在第4.11节“支持可访问性”中介绍了可访问性。
4.1.3双缓存
在更新组件(擦除然后重绘组件)时,会产生可察觉的闪烁。双缓存通过在屏外缓存区中更新组件,然后把屏外缓存区的相应部分拷贝到组件的屏上代表中来消除闪烁。
所有的Swing轻量组件都继承了双缓存它们显示内容的能力。一个屏外缓存(由Swing的RepaintManager维护)常用于双缓存JComponent的扩展。
图4-3示出了一个篮球图像的简单动画和含有可拖动的轻量组件的应用程序。
除了为双缓存轻量组件使用屏外缓存外,开发人员还可以为拖动轻量组件或实现动画等其他目的而使用屏外缓存。
4.1.4调试图形
4.1.5自动滚动
4.1.6工具提示
4.1.7键击处理和客户属性
4.2 JComponent类结构
4.2.1 Swing组件是AWT容器
例4-1 作为容器使用的Swing按钮
import javax.swing.*;
import java.awt.*;
public class ButtonAsContainer extends JApplet {
public void init() {
JButton b = new JButton("Swing Buttons Are Containers");
b.setLayout(new FlowLayout());
b.add(new Button("AWT Button"));
b.add(new JButton("Swing Button"));
getContentPane().add(b);
}
}
4.2.2最小尺寸、最大尺寸和首选尺寸
例4-2 为JComponent显式地设置首选大小
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
JComboBox sizeCombo = new JComboBox(new Object[] {
"null",
"100 x 100"
});
JList list = new JList(new Object[] {
"item 1",
"item 2",
"item 3",
"item 4",
"item 5",
});
public void init() {
final Container contentPane = getContentPane();
list.setBorder(
BorderFactory.createLineBorder(Color.black));
sizeCombo.setSelectedIndex(0);
contentPane.setLayout(new FlowLayout());
contentPane.add(list);
contentPane.add(new JLabel("preferred size for list:"));
contentPane.add(sizeCombo);
sizeCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int index = sizeCombo.getSelectedIndex();
if(index == 0)
list.setPreferredSize(null);
else
list.setPreferredSize(
new Dimension(100, 100));
list.revalidate();
}
});
}
}
4.3 绘制JComponent组件
4.3.1 Swing组件中的定制绘制
4.3.2在AWT组件中重载绘制方法
例4-3 为定制AWT组件而重载paint()
import java.applet.Applet;
import java.awt.*;
public class TestApplet extends Applet {
public void init() {
ImageCanvas imageCanvas = new ImageCanvas("sphere.gif");
//ImageCanvas imageCanvas = new ImageCanvas(
add(imageCanvas);
//setVisible(true);
}
}
class ImageCanvas extends Canvas {
Image image;
public ImageCanvas(String imageName) {
image = Toolkit.getDefaultToolkit().getImage(imageName);
MediaTracker mt = new MediaTracker(this);
try {
mt.addImage(image, 0);
mt.waitForID(0);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
}
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(null),
image.getHeight(null));
}
}
4.3.3在Swing组件中重载绘制方法
例4-4 带有从JComponent派生的图像画布的小应用程序
import javax.swing.*;
import java.awt.*;
public class TestApplet extends JApplet {
public void init() {
Container contentPane = getContentPane();
ImageCanvas imagePanel = new ImageCanvas(
"sphere.gif",
"a blue sphere");
imagePanel.setBorder(
BorderFactory.createTitledBorder("ImageCanvas"));
contentPane.setLayout(new FlowLayout());
contentPane.add(imagePanel);
}
}
例4-5 为定制Swing组件而重载paintComponent()
class ImageCanvas extends JPanel {
ImageIcon icon;
public ImageCanvas(String imageName, String description) {
//icon = new ImageIcon(imageName, description);
icon =new ImageIcon(this.getClass().getResource(imageName),description);
}
public void paintComponent(Graphics g) {
Insets insets = getInsets();
super.paintComponent(g);
icon.paintIcon(this, g, insets.left, insets.top);
}
public Dimension getPreferredSize() {
Insets insets = getInsets();
return new Dimension(
icon.getIconWidth() + insets.left + insets.right,
icon.getIconHeight() + insets.top + insets.bottom);
}
}
4.3.4 paint、repaint和update方法
4.3.5 validate、invalidate和revalidate方法
4.3.6不透明组件与透明组件的比较
例4-6 不透明测试小应用程序
public class OpaqueTest extends JApplet {
public void init() {
Container contentPane = getContentPane();
RainPanel rainPanel = new RainPanel();
ColoredPanel opaque = new ColoredPanel(),
transparent = new ColoredPanel();
// JComponents are opaque by default, so the opaque
// property only needs to be set for transparent
transparent.setOpaque(false);
rainPanel.add(opaque);
rainPanel.add(transparent);
contentPane.add(rainPanel, BorderLayout.CENTER);
}
}
例4-7 不容透明Swing组件
import javax.swing.*;
import java.awt.*;
public class OpaqueTest extends JApplet {
public void init() {
Container contentPane = getContentPane();
RainPanel rainPanel = new RainPanel();
ColoredPanel opaque = new ColoredPanel(),
transparent = new ColoredPanel();
// JComponents are opaque by default, so the opaque
// property only needs to be set for transparent
transparent.setOpaque(false);
rainPanel.add(opaque);
rainPanel.add(transparent);
contentPane.add(rainPanel, BorderLayout.CENTER);
System.out.println(opaque.isOpaque());
System.out.println(transparent.isOpaque());
}
}
class RainPanel extends JPanel {
ImageIcon rain = new ImageIcon(this.getClass().getResource("rain.gif"));
private int rainw = rain.getIconWidth();
private int rainh = rain.getIconHeight();
public void paintComponent(Graphics g) {
Dimension size = getSize();
for(int row=0; row < size.height; row += rainh)
for(int col=0; col < size.width; col += rainw)
rain.paintIcon(this,g,col,row);
}
}
class ColoredPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = getSize();
g.setColor(Color.black);
g.drawRect(0,0,size.width-1,size.height-1);
g.setColor(Color.red);
g.fillRect(size.width/2-25,size.height/2-25,50,50);
}
public Dimension getPreferredSize() {
return new Dimension(100,100);
}
}
4.3.7立即绘制Swing组件
例4-8 在事件处理方法中使用paintImmediately()
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestApplet extends JApplet {
public void init() {
Container contentPane = getContentPane();
final JPanel panel = new JPanel();
JButton button = new JButton("repaint");
panel.setBackground(Color.blue);
panel.setPreferredSize(new Dimension(100,100));
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
contentPane.add(panel);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Color c = panel.getBackground();
Dimension sz = panel.getSize();
panel.setBackground(
c == Color.blue ? Color.red : Color.blue);
panel.paintImmediately(
0,0,sz.width,sz.height);
// for illustrative purposes only
try {
Thread.currentThread().sleep(5000);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
});
}
}
4.4 双缓存
例4-9 双缓存测试小应用程序
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DoubleBufferingTest extends JApplet {
public void init() {
final JSlider slider =
new JSlider(JSlider.HORIZONTAL,0,100,50);
final Container contentPane = getContentPane();
JCheckBox dbcheckBox = new JCheckBox("double buffered");
JPanel controlPanel = new JPanel();
dbcheckBox.setSelected(true);
controlPanel.add(dbcheckBox);
slider.setPaintTicks(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(15);
contentPane.add(controlPanel, "North");
contentPane.add(slider, "Center");
dbcheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent event) {
if(event.getStateChange() == ItemEvent.SELECTED) {
slider.setDoubleBuffered(true);
}
else {
slider.setDoubleBuffered(false);
}
}
});
}
}
例4-10 为组件的容器禁用双缓存
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DoubleBufferingTest extends JApplet {
public void init() {
final Container contentPane = getContentPane();
JSlider slider = new JSlider(JSlider.HORIZONTAL,0,100,50);
JCheckBox dbcheckBox = new JCheckBox("double buffered");
JPanel controlPanel = new JPanel();
dbcheckBox.setSelected(true);
controlPanel.add(dbcheckBox);
slider.setPaintTicks(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(15);
contentPane.add(controlPanel, "North");
contentPane.add(slider, "Center");
dbcheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent event) {
JComponent cp = (JComponent)getContentPane();
JComponent rp = (JComponent)getRootPane();
if(event.getStateChange() == ItemEvent.SELECTED) {
rp.setDoubleBuffered(true);
cp.setDoubleBuffered(true);
}
else {
rp.setDoubleBuffered(false);
cp.setDoubleBuffered(false);
}
}
});
}
}
例4-11 调用RepaintManager.getDoubleBufferingEnabled()
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DoubleBufferingTest extends JApplet {
public void init() {
Container contentPane = getContentPane();
JCheckBox dbcheckBox = new JCheckBox("double buffered");
JPanel controlPanel = new JPanel();
final JSlider slider =
new JSlider(JSlider.HORIZONTAL,0,100,50);
dbcheckBox.setSelected(true);
controlPanel.add(dbcheckBox);
slider.setPaintTicks(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(15);
contentPane.add(controlPanel, "North");
contentPane.add(slider, "Center");
dbcheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent event) {
RepaintManager rm =
RepaintManager.currentManager(slider);
if(event.getStateChange() == ItemEvent.SELECTED) {
rm.setDoubleBufferingEnabled(true);
}
else {
rm.setDoubleBufferingEnabled(false);
}
}
});
}
}
例4-12 动画测试小应用程序
例4-13 AnimationPane类清单
4.5 调试图形
例4-14 为调试图形使用Log(日志)和Flash(闪烁)选项
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class DebugGraphicsTest extends JApplet {
private JSlider slider = new JSlider();
boolean logIsOn = false, flashIsOn = false;
public void init() {
Container cp = getContentPane();
RepaintManager rm =
RepaintManager.currentManager(slider);
rm.setDoubleBufferingEnabled(false);
cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
cp.add(slider);
cp.add(makeControlPanel());
slider.setEnabled(false);
}
private JPanel makeControlPanel() {
JPanel controls = new JPanel(),
checkBoxes = new JPanel();
JCheckBox logCheckBox = new JCheckBox("Log"),
flashCheckBox = new JCheckBox("Flash");
JButton repaintButton = new JButton("repaint");
final JSlider flashTimeSlider =
new JSlider(JSlider.HORIZONTAL,0,250,100);
flashTimeSlider.setPaintTicks(true);
flashTimeSlider.setMajorTickSpacing(10);
flashTimeSlider.setMinorTickSpacing(5);
controls.setLayout(new BoxLayout(controls,
BoxLayout.X_AXIS));
checkBoxes.setLayout(new BoxLayout(checkBoxes,
BoxLayout.Y_AXIS));
flashTimeSlider.setBorder(
BorderFactory.createTitledBorder("Flash Time"));
controls.setBorder(
BorderFactory.createTitledBorder("Controls"));
checkBoxes.add(logCheckBox);
checkBoxes.add(flashCheckBox);
controls.add(repaintButton);
controls.add(flashTimeSlider);
controls.add(checkBoxes);
repaintButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int opts = 0;
if(logIsOn) opts |= DebugGraphics.LOG_OPTION;
if(flashIsOn) opts |= DebugGraphics.FLASH_OPTION;
slider.setDebugGraphicsOptions(opts);
repaint();
}
});
flashTimeSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
DebugGraphics.setFlashTime(
flashTimeSlider.getValue());
}
});
flashCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
AbstractButton b = (AbstractButton)e.getSource();
if(b.isSelected()) flashIsOn = true;
else flashIsOn = false;
}
});
logCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
AbstractButton b = (AbstractButton)e.getSource();
if(b.isSelected()) logIsOn = true;
else logIsOn = false;
}
});
return controls;
}
public static void main(String args[]) {
final JFrame f = new JFrame();
JApplet applet = new DebugGraphicsTest();
applet.init();
f.setContentPane(applet.getContentPane());
f.setBounds(100,100,300,175);
f.setTitle("DebugGraphicsTest");
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
f.dispose();
System.exit(0);
}
});
}
}
4.6 自动滚动
例4-15 包裹在滚动窗格中的一个列表
import javax.swing.*;
import java.awt.*;
public class TestApplet extends JApplet {
public void init() {
String[] items = { "one", "two", "three",
"four", "five", "six" };
Container contentPane = getContentPane();
JList list = new JList(items);
list.setVisibleRowCount(3);
contentPane.setLayout(new FlowLayout());
contentPane.add(new JScrollPane(list));
}
}
例4-16 自动滚动测试小应用程序
例4-17 AutoscrollViewport列表
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class AutoscrollViewport extends JViewport {
Point scrollTo = new Point(), last = new Point();
boolean manualDragUnderway = false;
final int increment;
public AutoscrollViewport(Component component, int inc) {
this.increment = inc;
setView(component);
setAutoscrolls(true);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
last.x = e.getPoint().x;
last.y = e.getPoint().y;
manualDragUnderway = true;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Point drag = e.getPoint();
Point viewPos = getViewPosition();
Point offset = new Point(drag.x - last.x,
drag.y - last.y);
last.x = drag.x;
last.y = drag.y;
if(contains(drag)) {
if(manualDragUnderway) {
scrollTo.x = viewPos.x - offset.x;
scrollTo.y = viewPos.y - offset.y;
setViewPosition(scrollTo);
}
}
else { // autoscrolling ...
Rectangle bounds = getBounds();
manualDragUnderway = false;
if(drag.x > bounds.x + bounds.width) {
// scroll right
viewPos.x -= increment;
setViewPosition(viewPos);
}
if(drag.x < 0) {
// scroll left
viewPos.x += increment;
setViewPosition(viewPos);
}
if(drag.y > bounds.y + bounds.height) {
// scroll down
viewPos.y -= increment;
setViewPosition(viewPos);
}
if(drag.y < 0) {
// scroll up
viewPos.y += increment;
setViewPosition(viewPos);
}
}
}
});
}
}
4.7 工具提示
例4-18 为一个按钮设置工具提示文本
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ToolTipTest extends JApplet {
public void init() {
Container contentPane = getContentPane();
JButton button = new JButton("I've got a tooltip");
button.setMnemonic(KeyEvent.VK_G);
button.setToolTipText(
"rather lengthy tooltip text for button");
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
}
}
4.7.1基于鼠标位置的工具提示
例4-19 根据鼠标位置来显示不同的工具提示
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ToolTipsBasedOnMousePosition extends JApplet {
public void init() {
Container contentPane = getContentPane();
//ImageMap map = new ImageMap("tiger.gif");
Icon icon = new ImageIcon(this.getClass().getResource("tiger.gif"));
ImageMap map = new ImageMap(icon);
contentPane.setLayout(new FlowLayout());
contentPane.add(map);
}
}
class ImageMap extends JLabel {
private Rectangle teeth= new Rectangle(62,203,80,55),
nose = new Rectangle(37,164,130,30),
ear = new Rectangle(228,10,65,55),
rEye = new Rectangle(137,103,20,17),
lEye = new Rectangle(65,97,16,15);
//public ImageMap(String imageName) {
public ImageMap(Icon imageName) {
//super(new ImageIcon(imageName));
super(imageName);
setToolTipText("tiger!");
}
public String getToolTipText(MouseEvent e) {
Point p = e.getPoint();
String s = null;
if(teeth.contains(p)) s = "ooooh, big teeth!";
else if(nose.contains(p)) s = "keen sense of smell";
else if(ear.contains(p)) s = "acute hearing";
else if(rEye.contains(p) || lEye.contains(p))
s = "excellent vision";
return s == null ? getToolTipText() : s;
}
}
4.7.2工具提示的首选位置
4.7.3定制工具提示的行为
4.7.4定制工具提示的界面样式
4.8 键击处理
例4-20 处理嵌套键击
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class KeystrokeTest extends JApplet {
private JButton button = new JButton("button");
public void init() {
Container contentPane = getContentPane();
JPanel panel = new JPanel();
JCheckBox checkbox = new JCheckBox("checkbox");
JButton southButton = new JButton("south button");
Listener listener = new Listener();
panel.setBorder(
BorderFactory.createTitledBorder(
("Ancestor of button and checkbox")));
checkbox.registerKeyboardAction(
listener,
KeyStroke.getKeyStroke(KeyEvent.VK_F,0,false),
JComponent.WHEN_FOCUSED);
panel.registerKeyboardAction(
listener,
KeyStroke.getKeyStroke(KeyEvent.VK_A,
InputEvent.ALT_MASK, false),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
southButton.registerKeyboardAction(
listener,
KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true),
JComponent.WHEN_IN_FOCUSED_WINDOW);
panel.add(button);
panel.add(checkbox);
contentPane.add(panel, "Center");
contentPane.add(southButton, "South");
}
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
String cname = src.getClass().getName();
if(src instanceof JCheckBox) {
System.out.print("'f' key PRESSED when checkbox");
System.out.println(" had focus");
}
else if(src instanceof JPanel) {
System.out.print("'ALT-a' key PRESSED when ancestor");
System.out.println(" of titled panel had focus");
}
else if(src instanceof JButton) {
System.out.print("'w' key RELEASED when any");
System.out.println(" component in window had focus");
}
System.out.println("Source: " + cname);
System.out.println();
}
}
4.9 客户属性
例4-21 用客户属性把一个动态目标分配给一个按钮
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
public class ClientPropertiesTest extends JApplet {
JButton button = new JButton("toggle target color");
JComboBox targetCombo = new JComboBox();
JPanel[] targets = { new JPanel(),
new JPanel(),
new JPanel() };
public void init() {
Container contentPane = getContentPane();
Dimension targetPreferredSize = new Dimension(100,100);
JPanel targetPanel = new JPanel();
for(int i=0; i < targets.length; ++i) {
targets[i].setBackground(Color.blue);
targets[i].setPreferredSize(targetPreferredSize);
targetPanel.add(targets[i]);
}
targetCombo.addItem("left");
targetCombo.addItem("center");
targetCombo.addItem("right");
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
contentPane.add(targetCombo);
contentPane.add(targetPanel);
button.putClientProperty("target", targets[0]);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component c =
(Component)button.getClientProperty("target");
if(c != null) {
Color bg = c.getBackground();
c.setBackground(bg == Color.blue ?
Color.red : Color.blue);
c.repaint();
}
}
});
targetCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
button.putClientProperty(
"target",
targets[targetCombo.getSelectedIndex()]);
}
});
button.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if(e.getPropertyName().equals("target")) {
showStatus(
(String)targetCombo.getSelectedItem() +
" panel set as target");
}
}
});
}
public static void main(String args[]) {
final JFrame f = new JFrame();
JApplet applet = new ClientPropertiesTest();
applet.init();
f.setContentPane(applet.getContentPane());
f.setBounds(100,100,300,250);
f.setTitle("ClientPropertiesTest");
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
f.dispose();
System.exit(0);
}
});
}
}
4.10 焦点管理
4.10.1 JComponent的焦点属性
例4-22 为Swing组件指定焦点属性
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
private JButton button_1 = new NotFocusTraversableButton(),
button_2 = new ButtonThatManagesFocus(),
button_3 = new JButton("regular button"),
button_4 = new JButton("regular button"),
button_5 = new JButton("request focus disabled"),
button_6 = new JButton(
"next focusable component set to Manages Focus button");
public void init() {
Container contentPane = getContentPane();
FocusCycleRootPanel panel = new FocusCycleRootPanel();
button_5.setRequestFocusEnabled(false);
button_6.setNextFocusableComponent(button_2);
panel.add(button_3);
panel.add(button_4);
panel.add(button_5);
contentPane.setLayout(new FlowLayout());
contentPane.add(button_1);
contentPane.add(button_2);
contentPane.add(panel);
contentPane.add(button_6);
}
}
class ButtonThatManagesFocus extends JButton {
public ButtonThatManagesFocus() {
super("Manages Focus");
}
public boolean isManagingFocus() {
return true;
}
public void processComponentKeyEvent(KeyEvent e) {
System.out.println(e);
}
}
class NotFocusTraversableButton extends JButton {
public NotFocusTraversableButton() {
super("Not Focus Traversable");
}
public boolean isFocusTraversable() {
return false;
}
}
class FocusCycleRootPanel extends JPanel {
public FocusCycleRootPanel() {
setBorder(BorderFactory.createTitledBorder(
"FocusCycleRoot Panel"));
}
public boolean isFocusCycleRoot() {
return true;
}
}
4.10.2焦点管理器
例4-23 实现一个定制的焦点管理器
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
private JButton button_1 = new JButton("button one"),
button_2 = new JButton("button two"),
button_3 = new JButton("button three"),
button_4 = new JButton("button four"),
button_5 = new JButton("button five"),
button_6 = new JButton("button six");
public void init() {
Container contentPane = getContentPane();
javax.swing.FocusManager.setCurrentManager(
new CustomFocusManager());
contentPane.setLayout(new FlowLayout());
contentPane.add(button_1);
contentPane.add(button_2);
contentPane.add(button_3);
contentPane.add(button_4);
contentPane.add(button_5);
contentPane.add(button_6);
}
}
class CustomFocusManager extends DefaultFocusManager {
public boolean compareTabOrder(Component a, Component b) {
Point location_a = a.getLocation(),
location_b = b.getLocation();
int ax = location_a.x, ay = location_a.y;
int bx = location_b.x, by = location_b.y;
if(Math.abs(ay - by) < 10) {
return (bx < ax);
}
return (ay > by);
}
}
4.11 支持可访问性
例4-24 获得可访问性信息
import javax.swing.*;
import javax.accessibility.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
JLabel label = new JLabel("First Name:");
JButton showButton = new JButton(
"show accessible information");
final JTextField field = new JTextField(15);
AccessibleContext fieldContext =
field.getAccessibleContext();
fieldContext.setAccessibleName("First Name");
fieldContext.setAccessibleDescription(
"Enter your first name");
contentPane.setLayout(new FlowLayout());
contentPane.add(showButton);
contentPane.add(label);
contentPane.add(field);
showButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
AccessibleContext context;
AccessibleRole role;
context = field.getAccessibleContext();
role = context.getAccessibleRole();
System.out.print("Accessible Role: ");
System.out.println(
context.getAccessibleRole());
System.out.print("Accessible Description: ");
System.out.println(
context.getAccessibleDescription());
System.out.print("Accessible Name: ");
System.out.println(
context.getAccessibleName());
}
});
}
}
相关推荐
Java Swing 是Java平台上用于构建图形用户界面(GUI)的库,它是Java Foundation Classes (JFC) 的一部分。Swing 提供了一套丰富的组件集合,这些组件可以用来创建功能丰富的桌面应用程序。这本书《Java Swing》由O'...
Java Swing 是Java GUI(图形用户界面)开发的重要库,它基于Java AWT(Abstract Window Toolkit)并提供了更丰富、更现代的组件和设计模式。本教程将深入探讨Swing的相关知识,帮助你构建功能强大的桌面应用程序。 ...
**第4章 JComponent类**: JComponent类是所有Swing组件的父类,它扩展了AWT的Component类。JComponent引入了属性如背景色、前景色、字体等,并提供了添加监听器、设置布局管理器、绘制自定义图形的能力。开发者可以...
本章"Java Swing图形界面开发与案例详解"深入讲解了Swing组件、布局管理以及事件处理等核心概念,旨在帮助学习者掌握Swing的基本用法并能够实际操作创建丰富的GUI应用程序。 1. **Swing组件**: Swing提供了许多组件...
Java Swing是Java GUI(图形用户界面)开发的重要库,它基于Java AWT(Abstract Window Toolkit)并提供了更丰富的组件和事件处理机制。本资源“java swing 2nd源码”显然是来自一本关于Java Swing的第二版书籍,...
在Java Swing第二版中,涵盖了更深入的Swing组件使用、布局管理、事件处理以及自定义组件等内容。这本书的源码提供给读者实践和探索Swing API的机会。 1. **Swing组件**:Swing提供了许多组件,如JButton、JLabel、...
在Java Swing中,基本组件如按钮(JButton)、文本框(JTextField)、标签(JLabel)等,都是继承自JComponent类的特定类。开发者可以通过这些组件搭建各种复杂的用户界面。例如,JFrame是所有Swing应用程序的基础...
第17章主要介绍了Java语言中的图形用户界面(GUI)设计,这是使程序更加用户友好和易用的关键。GUI组件的灵活性和多样性使得开发者能够创建各种各样的交互式界面。本章的学习目标涵盖了许多核心的GUI组件和事件处理...
Java Swing 是Java编程语言中用于构建图形用户界面(GUI)的一个工具包,它是Java Foundation Classes (JFC)的一部分。这个“java swing小程序”压缩包很可能包含了一些示例代码,可以帮助初学者或者开发者更好地...
Java图形界面设计主要涉及到两个核心库:AWT(Abstract Windowing Toolkit)和Swing。AWT是Java早期提供的用于创建图形用户界面的基础框架,而Swing则是后来发展起来的更加强大和灵活的GUI库。 9.1 Java图形界面...
Java Swing 是Java编程语言中的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分。Swing提供了一套丰富的组件,用于创建桌面应用程序,包括按钮、文本框、菜单、滚动面板等。本教程将围绕...
Swing是Java图形用户界面(GUI)编程中的一个重要组成部分,它是建立在AWT基础之上的一个高级GUI库。AWT(抽象窗口工具包)是Java最初的GUI库,但随着时间的发展和技术的进步,AWT逐渐暴露出一些不足之处,无法满足现代...
Swing是Java编程语言中用于构建用户界面的GUI(图形用户界面)工具包,它是Java Foundation Classes (JFC) 的一部分。这篇博文“对Swing的一点理解(一)”可能探讨了Swing的基本概念、组件使用以及如何通过源码实现...
根据提供的文件信息,可以看出标题与描述提及的是关于Java Swing程序设计的内容,但给出的部分内容实际上是一封具有幽默性质的情侣间的通信,并未涉及任何Swing编程的信息。因此,本回答将依据标题和描述中提到的...
书中还特别关注了标签(Label)和图标(Icon)的使用,第4章“Labels and Icons”详细介绍了如何在Swing应用程序中有效地使用这些视觉元素,提升用户体验。 综上所述,《Java Swing:构建图形用户界面的全面指南》...
JavaSwing是Java平台上用于构建桌面应用程序的GUI(图形用户界面)工具包,它是Java Foundation Classes (JFC)的一部分。本项目"JavaSwing实现飞机大战"是一个基于JavaSwing开发的经典游戏,它展示了如何利用Java...
这个名为“Java图形与动画编程实例2”的资源是继第一部分之后的进阶教程,旨在帮助程序员更深入地理解和掌握如何在Java环境中创建引人入胜的图形和动态效果。 首先,我们要理解Java中的图形API。Java标准版(Java ...
Java Swing 是Java GUI(图形用户界面)库的一部分,用于创建桌面应用程序。在Swing中,时间控件通常指的是可以展示和处理日期与时间的组件。本主题将深入讲解如何在Java Swing中创建和使用时间控件,以及如何利用...
Java Swing 是一个用于创建桌面应用程序的 Java 库,它是 Java Foundation Classes (JFC) 的一部分。Swing 提供了一组可定制的、图形用户界面 (GUI) 组件,用于构建功能丰富的应用程序。在 Java 开发环境中,...
Java Swing 是Java平台上用于构建图形用户界面(GUI)的一个丰富的库。它提供了许多组件和工具,使得开发者可以创建出功能齐全、美观的桌面应用程序。在本主题中,我们重点讨论"java swing 界面源码",这是一份包含...