1

这是我在这个网站上的第一个问题,虽然不是我第一次进入以清除我的疑虑,很棒的网页。:)

我正在编写一个突出显示 JTextPane 中代码的 java 程序,并且我正在更改突出显示的完成方式。我正在使用 JTabbedPane 让用户同时编辑多个文件,并且我曾经使用 Timer 执行文档突出显示,现在我构建了一个在单独线程中运行的突出显示队列并实现了一个 DocumentListener 队列发生变化时的文件。

但是我有一个很大的问题,如果我通过 DocumentListener 添加文档,Highlight 过程需要很长时间,而如果我通过直接从 JTextPane 获取文档将其添加到主类中,则只需几毫秒。我在我的代码中执行了多个基准测试,发现从 DocumentListener 添加文档时需要花费大量时间执行的是方法 Document.setCharacterAttributes()。

下面是通过 DocumentListener 添加文档的方法:

// eventType: 0 - insertUpdate / 1- removeUpdate
private void queueChange(javax.swing.event.DocumentEvent e, int eventType){
    StyledDocument doc = (StyledDocument) e.getDocument();
    int changeLength = e.getLength();
    int changeOffset = e.getOffset();
    int length = doc.getLength();
    String title = (String) doc.getProperty("title");

    String text;
    try {
        text = doc.getText(0, length);

        if (changeLength != 1) {
            Element element = doc.getDefaultRootElement();
            int startLn = element.getElement(element.getElementIndex(changeOffset)).getStartOffset();
            int endLn = element.getElement(element.getElementIndex(changeOffset + changeLength)).getEndOffset() - 1;

            Engine.addDocument(doc, startLn, endLn, title, text);
        } else {
            if(eventType == 1){
                changeOffset = changeOffset - changeLength;
            }
            int startLn = text.lastIndexOf("\n", changeOffset) + 1;
            int endLn = text.indexOf("\n", changeOffset);

            if (endLn < 0) {
                if (length != startLn) {
                    endLn = length;

                    Engine.addDocument(doc, startLn, endLn, title, text);
                }
            } else if (startLn != endLn && startLn < endLn) {
                Engine.addDocument(doc, startLn, endLn, title, text);
            }
        }
    } catch (BadLocationException ex) {
        Engine.crashEngine();
    }
}

如果我使用这种方法添加一个包含 2k 行的文档,则需要大约 1900 毫秒来突出显示整个文档,而如果我使用插入符号监听方法将文档添加到突出显示队列中,则需要大约 500 毫秒。

这是插入符号侦听方法的一部分,用于在加载整个文档时突出显示它们:

if (loadFile == true) {
    isKey = false;
    doc = edit[currentTab].Editor.getStyledDocument();
    try {
        Highlight.addDocument(doc, 0, doc.getLength(),
                Scripts.getTitleAt(currentTab), doc.getText(0, doc.getLength()));
    } catch (BadLocationException ex) {
        ex.printStackTrace();
    }
    loadFile = false;
}

注意:Highlight/Engine.addDocument() 方法有五个参数:(StyledDocument doc,int start, int end, String tabTitle, String docText)。开始和结束都指示需要突出显示的区域。

我将不胜感激与此问题相关的任何帮助,因为我已经尝试解决了几天,但在 Internet 上找不到类似的东西。:(

顺便说一句,有人知道 Document.setCharacterAttributes 和 Document.setParagraphAttributes 之间的实际区别吗?:P

4

2 回答 2

0

您可以尝试设置一个标志,指示它是用户更改还是您的 API 更改。在 Engine.addDocument() 的开头将标志设置为 API 状态,并在更改完成后将其重置。在您的侦听器中检查标志并跳过 API 的更改。您写了“我使用通过设置文档的一部分的字符属性来突出显示文本,因此该方法不是插入更多文本”。我不确定它不会插入文本。例如,您有“这是一个粗体文本”,然后您选择“粗体”并将属性更改为粗体。原始元素被分离,并出现 3 个新元素。我没有测试它,但它可能会调用 insertUpdate() 和 removeUpdate()

有谁知道 Document.setCharacterAttributes 和 Document.setParagraphAttributes 之间的实际区别?有段落和字符属性。字符属性是字体大小、系列、样式、颜色。段落属性是对齐、缩进、行距。实际上,段落是 char 元素的父母。

于 2011-01-05T08:13:09.207 回答
0

也许您的代码中有某种递归导致了问题。使用 DocumentEvent,您应该只担心添加和删除。您无需担心更改,因为这些是属性更改。

也许您添加了一些安排突出显示的文本,但是当您更改文本的属性时,您会安排另一个突出显示任务。

于 2011-01-05T06:57:03.663 回答