Module java.desktop
Package javax.swing.text

Class AbstractDocument

java.lang.Object
javax.swing.text.AbstractDocument
所有已实现的接口:
Serializable, Document
直接已知的子类:
DefaultStyledDocument, PlainDocument

public abstract class AbstractDocument extends Object implements Document, Serializable
作为实现文档接口的实现,用作实现各种文档的基础。在这个级别上,几乎没有策略,因此使用难度相应增加。

此类实现了文档的锁定机制。它允许多个读取者或一个写入者,并且写入者必须等到文档的所有观察者被通知前的更改完成后才能开始对文档进行另一个变更。读取锁定是通过render方法获取和释放的。写入锁定是通过变异文档的方法获取的,并在方法调用期间保持。通知是在产生变异的线程上完成的,并且该线程在通知期间对文档具有完全读取访问权限,但其他读取者被排除在外,直到通知完成。通知是一个bean事件通知,不允许任何进一步的变异,直到所有监听器都被通知。

从此类继承的任何模型,并与从BasicTextUI派生的外观实现一起使用的文本组件可以安全地异步更新,因为如果文档是AbstractDocument类型,则对View层次结构的所有访问都由BasicTextUI序列化。锁定假定独立线程仅从DocumentListener方法访问View层次结构,并且一次只有一个事件线程处于活动状态。

如果需要并发支持,则有以下额外的含义。任何DocumentListener实现和任何UndoListener实现的代码路径必须是线程安全的,并且如果要避免死锁,则不得访问组件锁。JComponent上的repaintrevalidate方法是安全的。

AbstractDocument在文档末尾实现了一个隐含的断点。除其他外,这允许您将插入符定位在最后一个字符之后。因此,getLength返回的是Content长度减一。如果创建自己的Content,请确保初始化它具有额外的字符。请参考StringContent和GapContent以获取示例。这样做的另一个含义是模拟隐含结束字符的元素将具有endOffset == (getLength() + 1)。例如,在DefaultStyledDocument中,getParagraphElement(getLength()).getEndOffset() == getLength() + 1

警告: 此类的序列化对象将不兼容未来的Swing版本。当前的序列化支持适用于短期存储或在运行相同版本Swing的应用程序之间的RMI。从1.4开始,已将所有JavaBeans的长期存储支持添加到java.beans包中。请参见XMLEncoder

  • Field Details

    • listenerList

      protected EventListenerList listenerList
      文档的事件监听器列表。
    • BAD_LOCATION

      protected static final String BAD_LOCATION
      指示错误位置的错误消息。
      参见:
    • ParagraphElementName

      public static final String ParagraphElementName
      用于表示段落的元素的名称
      参见:
    • ContentElementName

      public static final String ContentElementName
      用于表示内容的元素的名称
      参见:
    • SectionElementName

      public static final String SectionElementName
      用于保存部分(行/段落)的元素的名称
      参见:
    • BidiElementName

      public static final String BidiElementName
      用于保存单向运行的元素的名称
      参见:
    • ElementNameAttribute

      public static final String ElementNameAttribute
      用于指定元素名称的属性的名称
      参见:
  • Constructor Details

    • AbstractDocument

      protected AbstractDocument(AbstractDocument.Content data)
      构造一个新的AbstractDocument,围绕某个指定的内容存储机制。
      参数:
      data - 内容
    • AbstractDocument

      protected AbstractDocument(AbstractDocument.Content data, AbstractDocument.AttributeContext context)
      构造一个新的AbstractDocument,围绕某个指定的内容存储机制。
      参数:
      data - 内容
      context - 属性上下文
  • Method Details

    • getDocumentProperties

      public Dictionary<Object,Object> getDocumentProperties()
      支持管理一组属性。调用者可以使用documentProperties字典向文档添加全局属性。
      返回:
      nullDictionary
      另请参阅:
    • setDocumentProperties

      public void setDocumentProperties(Dictionary<Object,Object> x)
      替换此文档的文档属性字典。
      参数:
      x - 新字典
      另请参阅:
    • fireInsertUpdate

      protected void fireInsertUpdate(DocumentEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      参数:
      e - 事件
      另请参阅:
    • fireChangedUpdate

      protected void fireChangedUpdate(DocumentEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      参数:
      e - 事件
      另请参阅:
    • fireRemoveUpdate

      protected void fireRemoveUpdate(DocumentEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      参数:
      e - 事件
      另请参阅:
    • fireUndoableEditUpdate

      protected void fireUndoableEditUpdate(UndoableEditEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      参数:
      e - 事件
      另请参阅:
    • getListeners

      public <T extends EventListener> T[] getListeners(Class<T> listenerType)
      返回当前注册为FooListener的所有对象的数组。使用addFooListener方法注册FooListener

      您可以使用类字面量(例如FooListener.class)指定listenerType参数。例如,您可以使用以下代码查询文档d的文档侦听器:

      DocumentListener[] mls = (DocumentListener[])(d.getListeners(DocumentListener.class));
      如果不存在此类侦听器,则此方法返回一个空数组。
      类型参数:
      T - 侦听器类型
      参数:
      listenerType - 请求的侦听器类型
      返回:
      在此组件上注册为FooListener的所有对象的数组,如果没有添加此类侦听器,则返回一个空数组
      抛出:
      ClassCastException - 如果listenerType未指定实现java.util.EventListener的类或接口
      自:
      1.3
      另请参阅:
    • getAsynchronousLoadPriority

      public int getAsynchronousLoadPriority()
      获取异步加载优先级。如果小于零,则不应异步加载文档。
      返回:
      异步加载优先级,如果文档不应异步加载,则返回-1
    • setAsynchronousLoadPriority

      public void setAsynchronousLoadPriority(int p)
      设置异步加载优先级。
      参数:
      p - 新的异步加载优先级;小于零的值表示文档不应异步加载
    • setDocumentFilter

      public void setDocumentFilter(DocumentFilter filter)
      设置DocumentFilter。将DocumentFilter传递给insertremove以有条件地允许插入/删除文本。null值表示不会发生过滤。
      参数:
      filter - 用于约束文本的DocumentFilter
      自:
      1.4
      另请参阅:
    • getDocumentFilter

      public DocumentFilter getDocumentFilter()
      返回负责插入/删除过滤的DocumentFilter。返回null表示不会进行过滤。
      返回:
      DocumentFilter
      自:
      1.4
      另请参阅:
    • render

      public void render(Runnable r)
      允许在存在货币的情况下安全地呈现模型,如果模型支持异步更新。给定的可运行对象将以允许其在执行期间安全读取模型而不进行更改的方式执行。可运行对象本身可能进行任何变更。

      此实现在运行时获取读取锁。可能会有多个可运行对象同时执行,只要有活动的呈现可运行对象,所有写入者都将被阻塞。如果可运行对象抛出异常,则其锁将被安全释放。没有保护可运行对象永远不会退出的情况。这将有效地使文档在其生命周期内被锁定。

      如果给定的可运行对象尝试在此实现中进行任何更改,将会发生死锁。没有跟踪单个呈现线程以便检测此情况,但子类可以承担跟踪它们的开销并抛出错误。

      此方法是线程安全的,尽管大多数Swing方法不是。有关更多信息,请参阅Swing中的并发性

      指定者:
      render 在接口 Document
      参数:
      r - 要执行的渲染器
    • getLength

      public int getLength()
      返回数据的长度。这是表示用户数据的内容字符数。
      指定者:
      getLength 在接口 Document
      返回:
      长度 >= 0
      另请参阅:
    • addDocumentListener

      public void addDocumentListener(DocumentListener listener)
      添加文档侦听器以通知任何更改。
      指定者:
      addDocumentListener 在接口 Document
      参数:
      listener - 要添加的DocumentListener
      另请参阅:
    • removeDocumentListener

      public void removeDocumentListener(DocumentListener listener)
      移除文档侦听器。
      指定者:
      removeDocumentListener 在接口 Document
      参数:
      listener - 要移除的DocumentListener
      另请参阅:
    • getDocumentListeners

      public DocumentListener[] getDocumentListeners()
      返回在此文档上注册的所有文档侦听器的数组。
      返回:
      所有此文档的DocumentListener或当前未注册文档侦听器的空数组
      自:
      1.4
      另请参阅:
    • addUndoableEditListener

      public void addUndoableEditListener(UndoableEditListener listener)
      添加撤消侦听器以通知任何更改。在UndoableEdit上执行的撤消/重做操作将导致适当的DocumentEvent被触发以保持视图与模型同步。
      指定者:
      addUndoableEditListener 在接口 Document
      参数:
      listener - 要添加的UndoableEditListener
      另请参阅:
    • removeUndoableEditListener

      public void removeUndoableEditListener(UndoableEditListener listener)
      移除撤消侦听器。
      指定者:
      removeUndoableEditListener 在接口 Document
      参数:
      listener - 要移除的UndoableEditListener
      另请参阅:
    • getUndoableEditListeners

      public UndoableEditListener[] getUndoableEditListeners()
      返回在此文档上注册的所有可撤销编辑监听器的数组。
      返回:
      此文档的所有UndoableEditListener或如果当前未注册任何可撤销编辑监听器,则返回空数组
      自:
      1.4
      另请参阅:
    • getProperty

      public final Object getProperty(Object key)
      查找属性值的便利方法。等效于:
       getDocumentProperties().get(key);
       
      指定者:
      getProperty 在接口 Document
      参数:
      key - 非null的属性键
      返回:
      此属性的值或null
      另请参阅:
    • putProperty

      public final void putProperty(Object key, Object value)
      存储属性值的便利方法。等效于:
       getDocumentProperties().put(key, value);
       
      如果valuenull,此方法将删除该属性。
      指定者:
      putProperty 在接口 Document
      参数:
      key - 非null的键
      value - 属性值
      另请参阅:
    • remove

      public void remove(int offs, int len) throws BadLocationException
      从文档中删除一些内容。删除内容会导致在实际更改正在进行时保持写锁定。观察者将在调用此方法的线程上收到更改通知。

      此方法是线程安全的,尽管大多数Swing方法不是。有关更多信息,请参阅Swing中的并发性

      指定者:
      remove 在接口 Document
      参数:
      offs - 起始偏移量 >= 0
      len - 要删除的字符数 >= 0
      抛出:
      BadLocationException - 给定的删除位置不是文档中的有效位置
      另请参阅:
    • replace

      public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException
      删除从offsetoffset + length的文本区域,并用text替换它。如何实现这一点取决于具体实现,一些实现可能将其视为两个不同的操作:先删除再插入,其他实现可能将替换视为一个原子操作。
      参数:
      offset - 子元素的索引
      length - 要删除的文本长度,可以为0表示不删除任何内容
      text - 要插入的文本,null表示不插入任何文本
      attrs - 指示插入文本属性的AttributeSet,null是合法的,通常被视为一个空的属性集,但确切的解释留给子类
      抛出:
      BadLocationException - 给定位置不是文档中的有效位置
      自:
      1.4
    • insertString

      public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
      向文档中插入一些内容。插入内容会导致在实际更改正在进行时保持写锁定,然后在抓取写锁定的线程上通知观察者。

      此方法是线程安全的,尽管大多数Swing方法不是。有关更多信息,请参阅Swing中的并发性

      指定者:
      insertString 在接口 Document
      参数:
      offs - 起始偏移量 >= 0
      str - 要插入的字符串;对于null/空字符串不执行任何操作
      a - 插入内容的属性
      抛出:
      BadLocationException - 给定的插入位置不是文档中的有效位置
      另请参阅:
    • getText

      public String getText(int offset, int length) throws BadLocationException
      获取文档中的文本序列。
      指定者:
      getText 在接口 Document
      参数:
      offset - 起始偏移量 >= 0
      length - 要检索的字符数 >= 0
      返回:
      文本
      抛出:
      BadLocationException - 给定范围包括文档中不是有效位置的位置
      另请参阅:
    • getText

      public void getText(int offset, int length, Segment txt) throws BadLocationException
      获取文档中给定部分包含的文本。

      如果txt参数上的partialReturn属性为false,则Segment中返回的数据将是请求的整个长度,可能是一个副本,也可能不是,具体取决于数据的存储方式。如果partialReturn属性为true,则只返回可以在不创建副本的情况下返回的文本量。对于需要扫描文档大部分内容的情况,使用部分返回将提供更好的性能。以下是使用部分返回访问整个文档的示例:

         int nleft = doc.getDocumentLength();
         Segment text = new Segment();
         int offs = 0;
         text.setPartialReturn(true);
         while (nleft > 0) {
             doc.getText(offs, nleft, text);
             // 处理文本
             nleft -= text.count;
             offs += text.count;
         }
       
      指定者:
      getText 在接口 Document
      参数:
      offset - 起始偏移量 >= 0
      length - 要检索的字符数 >= 0
      txt - 用于检索文本的Segment对象
      抛出:
      BadLocationException - 给定范围包括文档中不是有效位置的位置
    • createPosition

      public Position createPosition(int offs) throws BadLocationException
      返回一个将随着文档更改而跟踪更改的位置。

      此方法是线程安全的,尽管大多数Swing方法不是。有关更多信息,请参阅Swing中的并发性

      指定者:
      createPosition 在接口 Document
      参数:
      offs - 模型中的位置 >= 0
      返回:
      位置
      抛出:
      BadLocationException - 如果给定位置不代表关联文档中的有效位置
      另请参阅:
    • getStartPosition

      public final Position getStartPosition()
      返回表示文档开头的位置。返回的位置可以被视为跟踪更改并保持位于文档开头的位置。
      指定者:
      getStartPosition 在接口 Document
      返回:
      位置
    • getEndPosition

      public final Position getEndPosition()
      返回表示文档结尾的位置。返回的位置可以被视为跟踪更改并保持位于文档结尾的位置。
      指定者:
      getEndPosition 在接口 Document
      返回:
      位置
    • getRootElements

      public Element[] getRootElements()
      获取定义的所有根元素。通常,只会有一个根元素,因此默认实现是返回默认根元素。
      指定者:
      getRootElements 在接口 Document
      返回值:
      根元素
    • getDefaultRootElement

      public abstract Element getDefaultRootElement()
      返回应基于的根元素,除非提供了其他分配视图给元素结构的机制。
      指定者:
      getDefaultRootElement 在接口 Document
      返回值:
      根元素
      参见:
    • getBidiRootElement

      public Element getBidiRootElement()
      返回此文档的双向结构的根元素。其子元素表示具有给定Unicode双向级别的字符运行。
      返回值:
      此文档的双向结构的根元素
    • getParagraphElement

      public abstract Element getParagraphElement(int pos)
      获取包含给定位置的段落元素。子类必须自行定义段落的确切含义。但是,它们应该记住段落至少应该是运行Unicode双向算法的文本单元。
      参数:
      pos - 起始偏移量 >= 0
      返回值:
      元素
    • getAttributeContext

      protected final AbstractDocument.AttributeContext getAttributeContext()
      获取管理属性的上下文。此方法有效地建立了用于压缩AttributeSet信息的策略。
      返回值:
      上下文
    • insertUpdate

      protected void insertUpdate(AbstractDocument.DefaultDocumentEvent chng, AttributeSet attr)
      作为文本插入的结果更新文档结构。这将在写锁内发生。如果此类的子类重新实现此方法,它应该同时委托给超类。
      参数:
      chng - 更改的描述
      attr - 更改的属性
    • removeUpdate

      protected void removeUpdate(AbstractDocument.DefaultDocumentEvent chng)
      作为文本删除的结果更新任何文档结构。此方法在实际从内容中删除文本之前调用。这将在写锁内发生。如果此类的子类重新实现此方法,它应该同时委托给超类。
      参数:
      chng - 更改的描述
    • postRemoveUpdate

      protected void postRemoveUpdate(AbstractDocument.DefaultDocumentEvent chng)
      作为文本删除的结果更新任何文档结构。此方法在文本从内容中删除后调用。这将在写锁内发生。如果此类的子类重新实现此方法,它应该同时委托给超类。
      参数:
      chng - 更改的描述
    • dump

      public void dump(PrintStream out)
      提供诊断转储。
      参数:
      out - 输出流
    • getContent

      protected final AbstractDocument.Content getContent()
      获取文档的内容。
      返回值:
      内容
    • createLeafElement

      protected Element createLeafElement(Element parent, AttributeSet a, int p0, int p1)
      创建文档叶元素。用于创建表示文档结构的元素的挂钩。由于此实现将结构和内容分开,因此当内容扩展时,元素会自动增长,因此现有元素的拆分会跟随。文档本身决定如何生成元素以提供使用不同类型元素的灵活性。
      参数:
      parent - 父元素
      a - 元素的属性
      p0 - 范围的开始 >= 0
      p1 - 范围的结束 >= p0
      返回值:
      新元素
    • createBranchElement

      protected Element createBranchElement(Element parent, AttributeSet a)
      创建可以包含其他元素的文档分支元素。
      参数:
      parent - 父元素
      a - 属性
      返回值:
      元素
    • getCurrentWriter

      protected final Thread getCurrentWriter()
      如果存在当前的写线程,则获取该线程。这可用于区分方法是作为现有修改的一部分调用还是需要获取锁并启动新事务。
      返回值:
      当前主动修改文档的线程,如果没有正在进行修改,则返回null
    • writeLock

      protected final void writeLock()
      获取锁以开始更改此锁保护的文档。为了获得锁,不能进行写入、通知更改或读取。此外,一个线程允许获得多个writeLock,只要它不试图从文档通知中获得额外的writeLock。在DocumentListener通知中尝试从中获得writeLock将导致IllegalStateException。每个线程获得多个writeLock的能力允许子类获得writeLock,执行多个操作,然后释放锁。

      writeLock的调用必须与writeUnlock的调用平衡,否则Document将保持锁定状态,无法进行读取或写入。

      抛出:
      IllegalStateException - 非法锁定尝试时抛出。如果文档实现正确,只有在文档监听器尝试修改文档时才会发生这种情况。这种情况违反了bean事件模型,其中不保证传递顺序,所有监听器应在允许进一步变异之前得到通知。
    • writeUnlock

      protected final void writeUnlock()
      释放先前通过writeLock获得的写锁。在减少锁计数后,如果没有未完成的锁,则允许新的写入者或读取者。
      参见:
    • readLock

      public final void readLock()
      获取锁以开始从文档中读取某些状态。可以同时存在多个读取器。写入会阻塞读取器,直到向侦听器的更改通知完成。应非常小心地使用此方法,以避免意外地损害文档。它应始终与readUnlock平衡使用。
      参见:
    • readUnlock

      public final void readUnlock()
      执行读取解锁。这表示其中一个读取器已完成。如果没有更多读取器,则可以再次开始写入。这应该与readLock平衡,并且应该在finally语句中发生,以确保平衡。以下是一个示例。
      
           readLock();
           try {
               // do something
           } finally {
               readUnlock();
           }
       
      参见: