Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1476324
  • 博文数量: 295
  • 博客积分: 10051
  • 博客等级: 上将
  • 技术积分: 3850
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-11 08:50
文章分类

全部博文(295)

文章存档

2011年(1)

2009年(4)

2008年(290)

我的朋友

分类: Java

2008-04-17 15:49:09

第21章 文本基础

  Swing文本组件是相对比较简单的组件。它建立在由javax.swing.text包的类和接口提供的一个复杂的下层构件之上。本书将分三章来介绍Swing文本。本章主要讨论所有文本组件从JTextComponent类继承的基本功能。在第22章的“文本组件”中将讨论这些文本组件。在第23章的“定制文本组件”中将讨论Swing文本的更高级的主题,如视图、元素、属性集和风格。

21.1 Swing文本组件

 

21.2 动作

 

21.2.1 文本动作

例21-1 使用文本组件动作


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.util.*;

public class Test extends JFrame {
private JTextArea textArea = createTextArea();
private Action[] actions = textArea.getActions();

private JList actionList = createActionList(actions);
private JSplitPane splitPane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
new JScrollPane(textArea),
new JScrollPane(actionList));
public Test() {
Container contentPane = getContentPane();

splitPane.setDividerLocation(150);

contentPane.add(splitPane, BorderLayout.CENTER);
contentPane.add(GJApp.getStatusArea(),
BorderLayout.SOUTH);

}
private JList createActionList(Action[] actions) {
DefaultListModel model = new DefaultListModel();
final JList list = new JList(model);

list.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);

for(int i=0; i < actions.length; ++i) {
model.addElement(actions[i]);
}

list.setCellRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(
JList list, Object value,
int index, boolean isSelected,
boolean cellHasFocus) {
super.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);

Action action = (Action)value;
setText((String)action.getValue(Action.NAME));

return this;
}
});
list.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()) {
Action source =
(Action)actionList.getSelectedValue();

textArea.requestFocus();
source.actionPerformed(null);

GJApp.showStatus("Action: " +
(String)source.getValue(Action.NAME));
}
}
});

return list;
}
private JTextArea createTextArea() {
JTextArea textArea = new JTextArea(
"line one\nline two\nline three\nline four");

textArea.setFont(new Font("Dialog", Font.ITALIC, 24));
textArea.getCaret().setBlinkRate(0);
return textArea;
}
public static void main(String args[]) {
GJApp.launch(new Test(),
"Text Component Actions",300,300,450,300);
}
}
class GJApp extends WindowAdapter {
static private JPanel statusArea = new JPanel();
static private JLabel status = new JLabel(" ");
static private ResourceBundle resources;

public static void launch(final JFrame f, String title,
final int x, final int y,
final int w, int h) {
launch(f,title,x,y,w,h,null);
}
public static void launch(final JFrame f, String title,
final int x, final int y,
final int w, int h,
String propertiesFilename) {
f.setTitle(title);
f.setBounds(x,y,w,h);
f.setVisible(true);

statusArea.setBorder(BorderFactory.createEtchedBorder());
statusArea.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
statusArea.add(status);
status.setHorizontalAlignment(JLabel.LEFT);

f.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE);

if(propertiesFilename != null) {
resources = ResourceBundle.getBundle(
propertiesFilename, Locale.getDefault());
}

f.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.exit(0);
}
});
}
static public JPanel getStatusArea() {
return statusArea;
}
static public void showStatus(String s) {
status.setText(s);
}
static Object getResource(String key) {
if(resources != null) {
return resources.getString(key);
}
return null;
}
}


21.2.2 动作和编辑工作包

 

例21-2 用缺省编辑工具包访问动作


import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;

public class Test extends JApplet {
private JTextArea textArea = new JTextArea("some content");
private Hashtable actionTable = new Hashtable();

public Test() {
Container contentPane = getContentPane();

textArea.setFont(new Font("Dialog", Font.PLAIN, 24));

loadActionTable();

setJMenuBar(createMenu());
contentPane.add(textArea, BorderLayout.CENTER);
}
private void loadActionTable() {
Action[] actions = textArea.getActions();

for(int i=0; i < actions.length; ++i) {
actionTable.put(actions[i].getValue(Action.NAME),
actions[i]);
}
}
private Action getAction(String name) {
return (Action)actionTable.get(name);
}
private JMenuBar createMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu editMenu = new JMenu("Edit");

editMenu.add(getAction(DefaultEditorKit.cutAction));
editMenu.add(getAction(DefaultEditorKit.copyAction));
editMenu.add(getAction(DefaultEditorKit.pasteAction));

menuBar.add(editMenu);
return menuBar;
}
}


21.3 键映射

 

例21-3 设置键映射


import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Test extends JApplet {
private JTextArea textArea = new JTextArea("initial content");
private JCheckBox cbox = new JCheckBox("keymap added");
private Hashtable actionTable = new Hashtable();
private Keymap originalKeymap, newKeymap;

public void init() {
Container contentPane = getContentPane();

loadActionTable();
originalKeymap = textArea.getKeymap();
newKeymap = createKeymap();

textArea.setFont(new Font("Dialog", Font.PLAIN, 24));

contentPane.add(new ControlPanel(), BorderLayout.NORTH);
contentPane.add(textArea, BorderLayout.CENTER);
}
private Keymap createKeymap() {
Keymap map = JTextComponent.addKeymap("applet keymap",
textArea.getKeymap());

KeyStroke forwardKeyStroke =
KeyStroke.getKeyStroke(KeyEvent.VK_F,
InputEvent.ALT_MASK),
backwardKeyStroke =
KeyStroke.getKeyStroke(KeyEvent.VK_B,
InputEvent.ALT_MASK);
Action forwardAction =
getAction(DefaultEditorKit.forwardAction),
backwardAction =
getAction(DefaultEditorKit.backwardAction);

map.addActionForKeyStroke(forwardKeyStroke,
forwardAction);
map.addActionForKeyStroke(backwardKeyStroke,
backwardAction);
return map;
}
private void loadActionTable() {
Action[] actions = textArea.getActions();

for(int i=0; i < actions.length; ++i) {
actionTable.put(actions[i].getValue(Action.NAME),
actions[i]);
}
}
private Action getAction(String name) {
return (Action)actionTable.get(name);
}
class ControlPanel extends JPanel {
public ControlPanel() {
add(cbox);

cbox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textArea.setKeymap(cbox.isSelected() ?
newKeymap :
originalKeymap);

textArea.requestFocus();
}
});
}
}
}


21.4 文档

 

21.4.1 定制文档

 

例21-4 只可以输入整数的文档


import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;

public class Test extends JApplet {
JTextField tf = new JTextField(3);

public Test() {
Container contentPane = getContentPane();
JLabel label = new JLabel("Enter an Integer:");

tf.setDocument(new IntegerDocument());

contentPane.setLayout(new FlowLayout());
contentPane.add(label);
contentPane.add(tf);
}
}
class IntegerDocument extends PlainDocument {
public void insertString(int offset, String s,
AttributeSet attributeSet)
throws BadLocationException {
try {
Integer.parseInt(s);
}
catch(Exception ex) { // only allow integer values
Toolkit.getDefaultToolkit().beep();
return;
}
super.insertString(offset, s, attributeSet);
}
}


21.4.2 文档监听器

 

例21-5 使用文档监听器


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.util.*;
import java.io.*;

public class Test extends JFrame {
private JTextArea textArea = new JTextArea();
private Document document = textArea.getDocument();
private DefaultEditorKit kit = new DefaultEditorKit();
private Action saveAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
String s = JOptionPane.showInputDialog(
Test.this,
"Enter Filename:");
if(s != null) {
try {
kit.write(new FileWriter(s),
document, 0,
document.getLength());
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
};

public Test() {
Container contentPane = getContentPane();

try {
kit.read(new FileReader("Test.java"), document, 0);
}
catch(Exception ex) {
ex.printStackTrace();
}

final JTextArea status = new JTextArea();
JPanel p = new JPanel();
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
p, status);
sp.setDividerLocation(200);

saveAction.putValue(Action.NAME, "Save ...");
saveAction.setEnabled(false);

p.setLayout(new BorderLayout());
p.add(new JScrollPane(textArea), BorderLayout.CENTER);

contentPane.add(sp, BorderLayout.CENTER);

textArea.getDocument().addDocumentListener(
new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
saveAction.setEnabled(true);
updateStatus(e);
}
public void removeUpdate(DocumentEvent e) {
saveAction.setEnabled(true);
updateStatus(e);
}
public void changedUpdate(DocumentEvent e) {
saveAction.setEnabled(true);
updateStatus(e);
}
private void updateStatus(DocumentEvent e) {
status.append(e.getType().toString());
status.append(" Offset: " + e.getOffset());
status.append(" Length: " + e.getLength() + "\n");
}
});

setJMenuBar(createMenuBar());
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu editMenu = new JMenu("Edit");

editMenu.add(new DefaultEditorKit.CutAction());
editMenu.add(new DefaultEditorKit.CopyAction());
editMenu.add(new DefaultEditorKit.PasteAction());
editMenu.addSeparator();
editMenu.add(saveAction);

menuBar.add(editMenu);
return menuBar;
}
public static void main(String args[]) {
GJApp.launch(new Test(),
"Using Document Listeners",
300,300,650,500);
}
}
class GJApp extends WindowAdapter {
static private JPanel statusArea = new JPanel();
static private JLabel status = new JLabel(" ");
static private ResourceBundle resources;

public static void launch(final JFrame f, String title,
final int x, final int y,
final int w, int h) {
launch(f,title,x,y,w,h,null);
}
public static void launch(final JFrame f, String title,
final int x, final int y,
final int w, int h,
String propertiesFilename) {
f.setTitle(title);
f.setBounds(x,y,w,h);
f.setVisible(true);

statusArea.setBorder(BorderFactory.createEtchedBorder());
statusArea.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
statusArea.add(status);
status.setHorizontalAlignment(JLabel.LEFT);

f.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE);

if(propertiesFilename != null) {
resources = ResourceBundle.getBundle(
propertiesFilename, Locale.getDefault());
}

f.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.exit(0);
}
});
}
static public JPanel getStatusArea() {
return statusArea;
}
static public void showStatus(String s) {
status.setText(s);
}
static Object getResource(String key) {
if(resources != null) {
return resources.getString(key);
}
return null;
}
}


21.5 加字符与加重器

 

21.5.1 加字符

 

21.5.2 加字符监听器

 

例21-6 实现一个加字符监听器


import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JTextArea textArea = new JTextArea();

contentPane.add(textArea, BorderLayout.CENTER);

textArea.setFont(new Font("Dialog", Font.PLAIN, 24));

textArea.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
showStatus("Mark: " + e.getMark() +
" / Dot: " + e.getDot());
}
});
}
}


21.5.3 定制加字符

 

例21-7 实现一个定制加字符


import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JTextArea textArea = new JTextArea();

textArea.setCaret(new TriangleCaret(8));
textArea.setFont(new Font("Dialog", Font.ITALIC, 24));
contentPane.add(textArea, BorderLayout.CENTER);
}
}
class TriangleCaret extends DefaultCaret {
private int triangleWidth, left, right, top, bottom, middle;

public TriangleCaret(int triangleWidth) {
this.triangleWidth = triangleWidth;
}
public void paint(Graphics g) {
if(isVisible()) {
try {
JTextComponent comp = getComponent();
Rectangle r = comp.modelToView(getDot());

setLocations(r);
g.setColor(comp.getCaretColor());

g.drawLine(left, bottom, middle, top);
g.drawLine(middle, top, right, bottom);
g.drawLine(right, bottom, left, bottom);
}
catch(BadLocationException ex) {
ex.printStackTrace();
}
}
}
protected synchronized void damage(Rectangle r) {
if(r != null) {
setLocations(r);
x = left;
y = top;
width = right - left + 1;
height = bottom - top + 1;
}
}
private void setLocations(Rectangle r) {
left = r.x - triangleWidth/2;
right = r.x + triangleWidth/2;
bottom = r.y + r.height - 1;
top = bottom - triangleWidth;
middle = r.x;

repaint();
}
}


21.5.4 加重器

 

例21-8 一个定制的加重器


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JTextArea textArea = new JTextArea(
"File choosers, like option panes, are lightweight\n" +
"components that\n" +
"are meant to be placed ...");

textArea.setCaret(new BoxHighlightingCaret());
textArea.setFont(new Font("Dialog", Font.ITALIC, 24));

contentPane.add(new JScrollPane(textArea),
BorderLayout.CENTER);
}
}
class BoxHighlightingCaret extends DefaultCaret {
private static BoxHighlighterPainter painter =
new BoxHighlighterPainter(null);

public Highlighter.HighlightPainter getSelectionPainter(){
return painter;
}
static class BoxHighlighterPainter
extends DefaultHighlighter.DefaultHighlightPainter {
private Color color;

public BoxHighlighterPainter(Color color) {
super(color);
this.color = color;
}
public Shape paintLayer(Graphics g, int p0, int p1,
Shape shape, JTextComponent comp,
View view) {
Rectangle b = shape.getBounds();

try {
g.setColor(getColor(comp));

Rectangle r1 = comp.modelToView(p0);
Rectangle r2 = comp.modelToView(p1);

g.drawRect(r1.x, r1.y, // x,y
r2.x - r1.x - 1, // width
r1.height - 1); // height
}
catch(BadLocationException ex) {
ex.printStackTrace();
}
return b;
}
private Color getColor(JTextComponent comp) {
return color != null ? color :
comp.getSelectionColor();
}
}
}


21.6 撤销/恢复

 

例21-9 一个撤消和恢复的实现


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;

public class Test extends JApplet {
private JTextArea textArea = new JTextArea("some content");
private Document document = textArea.getDocument();
private UndoManager undoManager = new UndoManager();
private UndoLastAction undoAction = new UndoLastAction();
private RedoAction redoAction = new RedoAction();

public Test() {
Container contentPane = getContentPane();

createMenu();
contentPane.add(textArea, BorderLayout.CENTER);

textArea.setFont(new Font("Dialog", Font.PLAIN, 24));
document.addUndoableEditListener(
new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e){
undoManager.addEdit(e.getEdit());
undoAction.update();
redoAction.update();
}
});
}
private void createMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu editMenu = new JMenu("Edit");

editMenu.add(new DefaultEditorKit.CutAction());
editMenu.add(new DefaultEditorKit.CopyAction());
editMenu.add(new DefaultEditorKit.PasteAction());

editMenu.addSeparator();

editMenu.add(undoAction);
editMenu.add(redoAction);

menuBar.add(editMenu);
setJMenuBar(menuBar);
}
class RedoAction extends AbstractAction {
public RedoAction() {
super("Redo");
update();
}
public void actionPerformed(ActionEvent e) {
undoManager.redo();
undoAction.update();
update();
}
public void update() {
boolean canRedo = undoManager.canRedo();

if(canRedo) {
setEnabled(true);
putValue(Action.NAME,
undoManager.getRedoPresentationName());
}
else {
setEnabled(false);
putValue(Action.NAME, "Redo");
}
}
}
class UndoLastAction extends AbstractAction {
public UndoLastAction() {
super("Undo");
update();
}
public void actionPerformed(ActionEvent e) {
undoManager.undo();
redoAction.update();
update();
}
public void update() {
boolean canUndo = undoManager.canUndo();

if(canUndo) {
setEnabled(true);
putValue(Action.NAME,
undoManager.getUndoPresentationName());
}
else {
setEnabled(false);
putValue(Action.NAME, "Undo");
}
}
}
}

阅读(877) | 评论(0) | 转发(0) |
0

上一篇:第18章 组合框

下一篇:第22章 文本组件

给主人留下些什么吧!~~