《Java 2 图形设计卷Ⅱ- SWING》第4章 JComponent类

简介: 第4章 JComponent类  JComponent类是所有Swing轻量组件的基类,因此,我们单独用一章对它进行讨论。JComponent对Swing的意义就如同java.awt.Component对AWT的意义一样,它们都是它们各自框架组件的基类。

4 JComponent

  JComponent类是所有Swing轻量组件的基类,因此,我们单独用一章对它进行讨论。JComponentSwing的意义就如同java.awt.ComponentAWT的意义一样,它们都是它们各自框架组件的基类。
  作为所有Swing轻量组件的基类,JComponent提供了大量的基本功能。要全面了解Swing,就必须知道JComponent类提供的功能,还必须知道如何使用JComponent类。

4.1 JComponent类概览

  JComponent扩展java.awt.Container,而java.awt.Container又扩展java.awt.Component,因此,所有的Swing组件都是AWT容器。ComponentContainer类本身提供了大量的功能,因此,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轻量组件都继承了双缓存它们显示内容的能力。一个屏外缓存(SwingRepaintManager维护)常用于双缓存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.2AWT组件中重载绘制方法

 

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.3Swing组件中重载绘制方法

 

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 paintrepaintupdate方法

 

4.3.5 validateinvalidaterevalidate方法

 

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

}
});

}
}


目录
相关文章
|
18天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
34 6
|
5天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
33 17
|
1天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
19 4
|
2天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
9 2
|
6天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
10天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
10天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
10天前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
18 3
|
13天前
|
Java 程序员 测试技术
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
本文介绍如何通过自定义 IDEA 的 JUnit4 Test Class 模板,实现生成测试类时自动注入 logger 和被测 Service。
20 5
|
14天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3