JTextComponent类是 Swing 文本组件的基础。此类为所有后代提供以下可定制的功能:

一个称为* document *的模型,用于 管理 组件的内容。

一个视图,在屏幕上显示该组件。

一种称为“编辑器套件”的控制器,可以读写文本并使用actions实现编辑功能。

支持无限的撤消和重做。

可插入的插入符号以及对插入符号的支持会更改侦听器和导航过滤器。

请参阅名为TextComponentDemo的示例以探索这些功能。尽管TextComponentDemo示例包含JTextPane的自定义实例,但本节中讨论的功能由所有JTextComponent子类继承。

上方的文本组件是自定义的文本窗格。下部的文本组件是JTextArea的实例,该实例用作日志,报告对文本窗格内容所做的所有更改。窗口底部的状态行根据是否选择了文本来报告选择的位置或插入符号的位置。

Try this:

单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 TextComponentDemo。另外,要自己编译和运行示例,请查阅example index。

使用鼠标选择文本,然后将光标放在文本窗格中。有关选择和光标的信息显示在窗口底部。

通过在键盘上 Importing 来 Importing 文本。您可以使用键盘上的箭头键或四个 emacs 键绑定来移动插入符号:Ctrl-B(向后一个字符),Ctrl-F(向后一个字符),Ctrl-N(向下一行)和 Ctrl- P(上一行)。

打开“编辑”菜单,然后使用其菜单项在文本窗格中编辑文本。在窗口底部的文本区域中进行选择。由于文本区域不可编辑,因此只有“编辑”菜单的某些命令(如“复制到剪贴板”)起作用。不过,请务必注意,菜单在两个文本组件上均起作用。

使用“样式”菜单中的项目将不同的样式应用于文本窗格中的文本。

以TextComponentDemo示例为参考,本节涵盖以下主题:

将文本操作与菜单和按钮相关联

所有 Swing 文本组件均支持标准的编辑命令,例如剪切,复制,粘贴和插入字符。每个编辑命令由Action对象表示和实现。 (要了解有关操作的更多信息,请参见如何使用动作。)通过操作,您可以将命令与 GUI 组件(如菜单项或按钮)相关联,从而围绕文本组件构建 GUI。

您可以在任何文本组件上调用getActions方法,以接收包含该组件支持的所有操作的数组。也可以将动作数组加载到HashMap中,以便您的程序可以按名称检索动作。这是TextComponentDemo示例中的代码,该代码采用文本窗格中的操作并将其加载到HashMap中。

private HashMap createActionTable(JTextComponent textComponent) {

HashMap actions = new HashMap();

Action[] actionsArray = textComponent.getActions();

for (int i = 0; i < actionsArray.length; i++) {

Action a = actionsArray[i];

actions.put(a.getValue(Action.NAME), a);

}

return actions;

}

这是从哈希 Map 中按动作名称检索动作的方法:

private Action getActionByName(String name) {

return actions.get(name);

}

您可以在程序中逐字使用这两种方法。

以下代码显示了剪切菜单项是如何创建的以及与从文本组件中删除文本的操作相关联。

protected JMenu createEditMenu() {

JMenu menu = new JMenu("Edit");

...

menu.add(getActionByName(DefaultEditorKit.cutAction));

...

该代码使用前面显示的便捷方法按名称获取操作。然后将动作添加到菜单。这就是您需要做的。菜单和动作负责其他所有事项。请注意,操作的名称来自DefaultEditorKit。该工具包提供了用于基本文本编辑的操作,并且是 Swing 提供的所有编辑器工具包的超类。因此,它的功能可用于所有文本组件,除非 thay 被定制覆盖。

为了提高效率,文本组件共享操作。 getActionByName(DefaultEditorKit.cutAction)返回的Action对象由窗口底部不可编辑的JTextArea共享。这种共享 Feature 有两个重要方面:

通常,您不应修改从编辑器工具包获得的Action对象。如果这样做,更改将影响程序中的所有文本组件。

Action对象可以对程序中的其他文本组件进行操作,有时超出您的预期。在此示例中,即使无法编辑,JTextArea与JTextPane共享动作。 (在文本区域中选择一些文本,然后选择“剪切到剪贴板”菜单项.由于文本区域不可编辑,您会听到蜂鸣声.)如果您不想共享,请自己实例化Action对象。 DefaultEditorKit定义了许多有用的Action子类。

这是创建“样式”菜单并将其放入“粗体”菜单项的代码:

protected JMenu createStyleMenu() {

JMenu menu = new JMenu("Style");

Action action = new StyledEditorKit.BoldAction();

action.putValue(Action.NAME, "Bold");

menu.add(action);

...

StyledEditorKit提供Action子类,以实现样式文本的编辑命令。您将注意到,此代码不是从编辑器工具包获取操作,而是创建BoldAction类的实例。因此,此操作不会与任何其他文本组件共享,并且更改其名称不会影响任何其他文本组件。

将文本操作与按键关联

除了将动作与 GUI 组件相关联之外,您还可以通过使用文本组件的 ImportingMap 将动作与按键相关联。ImportingMap 在如何使用键绑定中描述。

TextComponentDemo示例中的文本窗格支持默认情况下不提供的四个键绑定。

Ctrl-B 将插入符号向后移动一个字符

Ctrl-F 将插入符号向前移动一个字符

Ctrl-N 可以将插入符号向下移动一行

Ctrl-P 将插入符号上移一行

以下代码将 Ctrl-B 键绑定添加到文本窗格。添加上面列出的其他三个绑定的代码是相似的。

InputMap inputMap = textPane.getInputMap();

KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_B,

Event.CTRL_MASK);

inputMap.put(key, DefaultEditorKit.backwardAction);

首先,代码获取文本组件的 ImportingMap。接下来,它找到一个表示 Ctrl-B 键序列的KeyStroke对象。最后,该代码将击键绑定到Action,后者将光标向后移动。

实现撤消和重做

实现撤消和重做有两个部分:

实现撤消和重做命令并为其提供用户interface。

第 1 部分:记住不可编辑

为了支持撤消和重做,文本组件必须记住发生的每个编辑,编辑的 Sequences 以及撤消每个编辑所需的内容。该示例程序使用UndoManager类的实例来 管理 其不可撤消的编辑列表。在声明成员变量的位置创建撤消 管理 器:

protected UndoManager undo = new UndoManager();

现在,让我们看一下程序如何发现不可撤消的编辑并将其添加到撤消 管理 器中。

只要对文档内容进行了不可撤消的编辑,文档就会通知感兴趣的侦听器。实现撤消和重做的重要步骤是在文本组件的文档上注册一个可撤消的编辑侦听器。以下代码将MyUndoableEditListener的实例添加到文本窗格的文档中:

doc.addUndoableEditListener(new MyUndoableEditListener());

我们的示例中使用的可撤消编辑监听器将编辑添加到撤消 管理 器的列表中:

protected class MyUndoableEditListener

implements UndoableEditListener {

public void undoableEditHappened(UndoableEditEvent e) {

//Remember the edit and update the menus

undo.addEdit(e.getEdit());

undoAction.updateUndoState();

redoAction.updateRedoState();

}

}

请注意,此方法更新两个对象:undoAction和redoAction。这些是分别附加到“撤消”和“重做”菜单项上的动作对象。下一步显示了如何创建菜单项以及如何执行这两个操作。有关不可撤消的编辑侦听器和不可撤消的编辑事件的一般信息,请参阅如何编写不可撤销的编辑侦听器。

Note:

默认情况下,每个可撤消的编辑都撤消单个字符 Importing。可以将编辑分组,以便将一系列按键组合到一个不可撤消的编辑中。以这种方式对编辑进行分组将需要您定义一个类,该类从文档中拦截可撤消的编辑事件,并在适当时进行合并,然后将结果转发给可撤消的编辑侦听器。

第 2 部分:实现撤消和重做命令

实现撤消和重做的第一步是创建要放入“编辑”菜单中的动作。

JMenu menu = new JMenu("Edit");

//Undo and redo are actions of our own creation

undoAction = new UndoAction();

menu.add(undoAction);

redoAction = new RedoAction();

menu.add(redoAction);

...

撤消和重做操作分别通过自定义AbstractAction子类UndoAction和RedoAction实现。这些类是示例的主类的内部类。

当用户调用undo命令时,UndoAction类的actionPerformed方法被调用:

public void actionPerformed(ActionEvent e) {

try {

undo.undo();

} catch (CannotUndoException ex) {

System.out.println("Unable to undo: " + ex);

ex.printStackTrace();

}

updateUndoState();

redoAction.updateRedoState();

}

此方法调用撤消 管理 器的undo方法,并更新菜单项以反映新的撤消/重做状态。

同样,当用户调用redo命令时,RedoAction类的actionPerformed方法被调用:

public void actionPerformed(ActionEvent e) {

try {

undo.redo();

} catch (CannotRedoException ex) {

System.out.println("Unable to redo: " + ex);

ex.printStackTrace();

}

updateRedoState();

undoAction.updateUndoState();

}

此方法与撤消类似,不同之处在于它调用撤消 管理 器的redo方法。

UndoAction和RedoAction类中的许多代码专用于启用和禁用当前状态的相应操作,并更改菜单项的名称以反映要撤消或重做的编辑。

Note:

TextComponentDemo示例中的撤消和重做实现来自 JDK 软件随附的NotePad演示。许多程序员也可以无需修改就复制撤消/重做的实现。

概念:关于文档

像其他 Swing 组件一样,文本组件从其数据视图中分离其数据(称为* model *)。如果您还不熟悉 Swing 组件使用的模型视图拆分,请参阅Using Models。

文本组件的模型称为* document *,是实现Documentinterface的类的实例。文档为文本组件提供以下服务:

包含文本。文档将文本内容存储在Element对象中,该对象可以表示任何逻辑文本结构,例如段落或共享样式的文本行。我们此处不描述Element个对象。

提供对通过remove和insertString方法编辑文本的支持。

通知文档侦听器和可撤消的编辑侦听器有关文本的更改。

管理Position对象,这些对象即使在文本被修改的情况下也可以跟踪文本中的特定位置。

允许您获取有关文本的信息,例如其 Long 度,以及作为字符串 的文本段。

Swing 文本包包含Document,StyledDocument的子interface,该子interface增加了对使用样式标记文本的支持。一个JTextComponent子类JTextPane要求其文档是StyledDocument而不是Document。

javax.swing.text软件包提供了以下文档类层次结构,它们为各种JTextComponent子类实现了专用文档:

PlainDocument是文本字段,密码字段和文本区域的默认文档。 PlainDocument提供了一个基本的文本容器,其中所有文本均以相同的字体显示。即使编辑器窗格是样式化的文本组件,默认情况下它也会使用PlainDocument的实例。标准JTextPane的默认文档是DefaultStyledDocument的实例,该实例是没有特定格式的样式化文本的容器。但是,任何特定的编辑器窗格或文本窗格使用的文档实例取决于绑定到它的内容的类型。如果使用setPage方法将文本加载到编辑器窗格或文本窗格中,则该窗格使用的文档实例可能会更改。有关详情,请参阅如何使用编辑器窗格和文本窗格。

尽管可以设置文本组件的文档,但是通常更容易允许它自动设置,并且在必要时使用文档过滤器来更改文本组件的数据设置方式。您可以通过安装文档过滤器或通过使用自己的文档组件替换文本组件的文档来实现某些自定义。例如,TextComponentDemo示例中的文本窗格具有文档过滤器,该过滤器限制了该文本窗格可以包含的字符数。

实现文档过滤器

要实现文档过滤器,请创建DocumentFilter的子类,然后使用AbstractDocument类中定义的setDocumentFilter方法将其附加到文档。尽管可能存在不从AbstractDocument降级的文档,但默认情况下,Swing 文本组件的文档使用AbstractDocument子类。

TextComponentDemo应用程序具有一个文档过滤器DocumentSizeFilter,该过滤器限制了文本窗格可以包含的字符数。这是创建过滤器并将其附加到文本窗格的文档的代码:

...//Where member variables are declared:

JTextPane textPane;

AbstractDocument doc;

static final int MAX_CHARACTERS = 300;

...

textPane = new JTextPane();

...

StyledDocument styledDoc = textPane.getStyledDocument();

if (styledDoc instanceof AbstractDocument) {

doc = (AbstractDocument)styledDoc;

doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));

}

为了限制文档中允许的字符,DocumentSizeFilter会覆盖DocumentFilter类的insertString方法,该方法在每次将文本插入到文档中时都会调用。它还会覆盖replace方法,该方法最有可能在用户粘贴新文本时被调用。通常,当用户键入或粘贴新文本或调用setText方法时,可能会导致文本插入。这是insertString方法的DocumentSizeFilter类的实现:

public void insertString(FilterBypass fb, int offs,

String str, AttributeSet a)

throws BadLocationException {

if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)

super.insertString(fb, offs, str, a);

else

Toolkit.getDefaultToolkit().beep();

}

replace的代码相似。 DocumentFilter类定义的方法的FilterBypass参数只是一个对象,该对象使文档可以以线程安全的方式进行更新。

由于前面的文档过滤器与文档数据的添加有关,因此它仅覆盖insertString和replace方法。大多数文档过滤器也会覆盖DocumentFilter的remove方法。

监听文档中的更改

您可以在文档上注册两种不同类型的侦听器:文档侦听器和可撤消的编辑侦听器。本小节介绍了文档侦听器。有关可撤消的编辑侦听器的信息,请参阅实现撤消和重做。

文档将对文档的更改通知已注册的文档侦听器。当从文档中插入文本或从中删除文本时,或文本样式更改时,请使用文档侦听器来创建响应。

每当对文本窗格进行更改时,TextComponentDemo程序就使用文档侦听器来更新更改日志。下面的代码行将MyDocumentListener类的实例注册为文本窗格文档中的侦听器:

doc.addDocumentListener(new MyDocumentListener());

这是MyDocumentListener类的实现:

protected class MyDocumentListener implements DocumentListener {

public void insertUpdate(DocumentEvent e) {

displayEditInfo(e);

}

public void removeUpdate(DocumentEvent e) {

displayEditInfo(e);

}

public void changedUpdate(DocumentEvent e) {

displayEditInfo(e);

}

private void displayEditInfo(DocumentEvent e) {

Document document = (Document)e.getDocument();

int changeLength = e.getLength();

changeLog.append(e.getType().toString() + ": "

+ changeLength + " character"

+ ((changeLength == 1) ? ". " : "s. ")

+ " Text length = " + document.getLength()

+ "." + newline);

}

}

侦听器实现三种方法来处理三种不同类型的文档事件:插入,删除和样式更改。 StyledDocument实例可以触发所有三种类型的事件。 PlainDocument个实例仅触发插入和删除事件。有关文档侦听器和文档事件的一般信息,请参见如何编写文档监听器。

请记住,此文本窗格的文档过滤器限制了文档中允许的字符数。如果您try添加超出文档过滤器允许范围的文本,则文档过滤器将阻止更改,并且不会调用侦听器的insertUpdate方法。仅当更改已发生时,才会将更改通知文档侦听器。

您可能需要在文档侦听器中更改文档的文本。 但是,绝对不要从文档侦听器中修改文本组件的内容. 如果这样做,程序可能会死锁。相反,您可以使用格式化的文本字段或提供文档过滤器。

聆听插入符号和选择的更改

TextComponentDemo程序使用插入符号侦听器显示插入符号的当前位置,或者如果选择了文本,则显示选择范围。

在此示例中,插入符号侦听器类是JLabel子类。这是创建插入标记侦听器标签并使之成为文本窗格的插入标记侦听器的代码:

//Create the status area

CaretListenerLabel caretListenerLabel = new CaretListenerLabel(

"Caret Status");

...

textPane.addCaretListener(caretListenerLabel);

插入标记侦听器必须实现一个方法caretUpdate,每次插入标记移动或选择更改时都会调用该方法。这是caretUpdate的CaretListenerLabel实现:

public void caretUpdate(CaretEvent e) {

//Get the location in the text

int dot = e.getDot();

int mark = e.getMark();

if (dot == mark) { // no selection

try {

Rectangle caretCoords = textPane.modelToView(dot);

//Convert it to view coordinates

setText("caret: text position: " + dot +

", view location = [" +

caretCoords.x + ", " + caretCoords.y + "]" +

newline);

} catch (BadLocationException ble) {

setText("caret: text position: " + dot + newline);

}

} else if (dot < mark) {

setText("selection from: " + dot + " to " + mark + newline);

} else {

setText("selection from: " + mark + " to " + dot + newline);

}

}

如您所见,此侦听器更新其文本标签以反映插入符或选择的当前状态。侦听器从插入符事件对象获取要显示的信息。有关插入符号侦听器和插入符号事件的一般信息,请参见如何编写插入符侦听器。

与文档侦听器一样,插入符号侦听器是被动的。它对插入符号或选择中的更改做出反应,但不更改插入符号或选择本身。如果要更改插入标记或选择,请使用导航过滤器或自定义插入标记。

实现导航过滤器类似于实现文档过滤器。首先,编写NavigationFilter的子类。然后使用setNavigationFilter方法将子类的实例附加到文本组件。

您可以创建一个自定义插入符号,以自定义插入符号的外观。要创建自定义插入记号,请编写实现Caretinterface的类-也许可以通过扩展DefaultCaret类来实现。然后在文本组件上提供类的实例作为setCaret方法的参数。

概念:关于编辑器套件

文本组件使用EditorKit将文本组件的各个部分绑在一起。编辑器工具包提供了视图工厂,文档,插入符号和操作。编辑器工具包还读取和写入特定格式的文档。尽管所有文本组件都使用编辑器工具包,但是某些组件隐藏了它们。您无法设置或获取文本字段或文本区域使用的编辑器套件。编辑器窗格和文本窗格提供getEditorKit方法来获取当前的编辑器工具包,并提供setEditorKit方法来对其进行更改。

对于所有组件,JTextComponent类都提供了 API,供您间接调用或自定义某些编辑器工具包功能。例如,JTextComponent提供read和write方法,它们调用编辑器工具包的read和write方法。 JTextComponent还提供了方法getActions,该方法返回组件支持的所有操作。

Swing 文本包提供以下编辑器工具包:

读取和写入纯文本,并提供一组基本的编辑命令。有关文本系统如何处理换行符的详细信息,请参见DefaultEditorKit API 文档。简要地说,' n'字符在内部使用,但是在写文件时使用文档或平台行分隔符。所有其他编辑器工具包都是DefaultEditorKit类的后代。

读取和写入样式文本,并为样式文本提供最少的操作集。此类是DefaultEditorKit的子类,并且是JTextPane默认使用的编辑器工具包。

读取,写入和编辑 HTML。这是StyledEditorKit的子类。

上面列出的每个编辑器工具包都已向JEditorPane类注册,并与该工具包读取,写入和编辑的文本格式相关联。将文件加载到编辑器窗格中时,该窗格将根据其注册的工具包检查文件的格式。如果找到支持该文件格式的已注册工具包,则窗格将使用该工具包读取文件,显示和编辑它。因此,编辑器窗格有效地将其自身转换为该文本格式的编辑器。您可以通过为其创建编辑器套件,然后使用JEditorPane的registerEditorKitForContentType来扩展JEditorPane以支持您自己的文本格式,以将您的套件与文本格式相关联。

java literals_Java8 中文教程相关推荐

  1. java swing 中文_java swing 中文教程.doc

    java swing 中文教程 作者:williamchen 译者:Matthew Chen 备注:本文是翻译,由于部分文本网上有提供,就直接使用了.作者的初稿,不是很规范的英文,但是内容值得一读,所 ...

  2. BlackBerry手机Java开发开发工具下载/签名申请/入门中文教程

    本地下载 BlackBerry Java Plug-in for Eclipsev1.1 http://g.csdn.net/5147163 更多下载 http://blackberry.csdn.n ...

  3. java中文数字改阿拉伯数字_[Java教程]Java实现中文数字转换为阿拉伯数字

    [Java教程]Java实现中文数字转换为阿拉伯数字 0 2015-05-19 16:00:20 /** * 中文數字转阿拉伯数组[十万九千零六十 --> 109060] * @author 雪 ...

  4. JavaTPoint Java 中文教程【翻译完成】

    原文:JavaTPoint 协议:CC BY-NC-SA 4.0 阶段:机翻(1) 危机只有发展到最困难的阶段,才有可能倒逼出有效的解决方案.--<两次全球大危机的比较研究> 在线阅读 在 ...

  5. Hyperledger Fabric Java SDK最新教程

    Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK ...

  6. Java NIO系列教程(五) 通道之间的数据传输

    在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...

  7. JAVA正则表达式实例教程(转帖收藏)

    So many open source projects. Why not Open your Documents? 1 JAVA正则表达式实例教程 12/11/2008 1.正则表达式的知识要点 1 ...

  8. Java NIO系列教程(四) Scatter/Gather

    转载自   Java NIO系列教程(四) Scatter/Gather 译文地址  作者:Jakob Jenkov   译者:郭蕾 Java NIO开始支持scatter/gather,scatte ...

  9. Netty4.x中文教程系列(二) Hello World !

    在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个N ...

最新文章

  1. OpenCV3编程入门(毛星云)之视频读取与播放
  2. C语言再学习 -- 位、字节、字、字长、字元的关系
  3. 黑盒之嵌入式操作系统鲁棒性研究
  4. P3964-[TJOI2013]松鼠聚会【计算几何】
  5. linux传文件file,linux文件的传输与压缩快速入门
  6. 关于fragment中使用onActivityResult
  7. H5学习之旅-H5的表单(11)
  8. Android doc|Getting Started| Training部分 --翻译 Working with System Permissions
  9. 一份完整的建模文档需涵盖的模块与指标
  10. 计算机台账管理工作总结,台账工作总结(共6篇汇总).doc.docx
  11. 蓝桥杯 ALGO-98 算法训练 数位分离
  12. 通过jQuery EasyUI实现基本的拖放,此为转发!!大家学习讨论
  13. Vue 爬坑之路(四)—— 与 Vuex 的第一次接触
  14. 大学毕业4年-回顾和总结(3)-投资理财观-图穷而真相现
  15. office2007无法使用宏的解决方法
  16. 【android studio】测试不同buf下flash的读写性能2
  17. js 获取ip地址进行跳转
  18. 语音识别基本原理学习
  19. “进大厂大半年,每个月都想走!”大公司 VS 小公司到底该如何选择?
  20. android pm list,Android pm命令

热门文章

  1. macOS 11+ Big Sur SIP 禁用部分项方法
  2. Jackson之注解大全
  3. Python and运算符
  4. 跨时代的AI新品——JetMax机械臂,带来人工智能新玩法!
  5. 【Qualcomm高通音频】如何使用QXDM、QCAT音频数据抓取
  6. 旷视API调用识别身份证
  7. 计算机网络如何选择路由器,无线路由器如何选择上网方式_路由器上网方式选哪个?-192路由网...
  8. 【KV260】KV260的PMOD接口介绍
  9. 信息中心网络ICN在卫星通信中的应用调研
  10. 逼死程序员的翟欣欣方首度发声了,居然这样说,你信不?