简体   繁体   English

鼠标单击后如何继续在JTextArea中自动滚动?

[英]How to continue autoscroll in JTextArea after mouse click?

I have a very useful autoscrolling JTextArea/JScrollPane that continuously appends lines of text at the bottom and scrolls up. 我有一个非常有用的自动滚动JTextArea / JScrollPane,它可以在底部连续添加文本行并向上滚动。 I'd like to be able to double-click on a word and copy it to the clipboard for further processing of that word. 我希望能够双击一个单词并将其复制到剪贴板以对该单词进行进一步处理。 But I'd like the autoscrolling to continue to scroll from the bottom. 但我希望自动滚动继续从底部滚动。

However, as soon as I press the mouse in the JTextArea, the scrolling stops. 但是,只要在JTextArea中按下鼠标,滚动就会停止。 The new lines are still added, but the scrolling freezes. 仍会添加新行,但滚动会冻结。 The vertical scroll bar then starts to move up, showing that the text is being added below the view area. 然后,垂直滚动条开始向上移动,表明正在将文本添加到视图区域下方。 I can manually scroll down with the scroll bar, but it is manual only. 我可以使用滚动条手动向下滚动,但这仅是手动的。 The autoscrolling has been disabled. 自动滚动已被禁用。

I suspect the issue is with focus. 我怀疑这个问题是重点。 Somehow, perhaps the autoscroll loses focus to the manual mouse event. 某种程度上,自动滚动可能会失去对手动鼠标事件的关注。 I have tried all kinds of fixes but nothing works. 我已经尝试了各种修复程序,但是没有任何效果。

I am using the very useful Caret update policy to enable the scrolling from the bottom. 我正在使用非常有用的插入符号更新策略来启用从底部滚动。

caret = (DefaultCaret) jTextArea1.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

Here is greatly-reduced but fully-functional Java code illustrating the issue. 这里是大大简化但功能齐全的Java代码,说明了此问题。

package demoswingworker;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.SwingWorker;
import javax.swing.text.DefaultCaret;

public class ScrollTextArea extends javax.swing.JFrame {

String[] sentences;
Map sentenceMap = new TreeMap();

DefaultCaret caret;

public ScrollTextArea() {
initComponents();

caret = (DefaultCaret) jTextArea1.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
this.setLocation(0, 0);
this.setSize(140, 300);
this.setVisible(true);

for (int i = 0; i < 100; i++) {
    sentenceMap.put(i, i + "-abcdef");
}
scroll();
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jScrollPane1 = new javax.swing.JScrollPane();
    jTextArea1 = new javax.swing.JTextArea();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setBackground(new java.awt.Color(255, 153, 0));
    setFont(new java.awt.Font("Times New Roman", 1, 14)); // NOI18N

    jTextArea1.setBackground(new java.awt.Color(255, 153, 0));
    jTextArea1.setColumns(20);
    jTextArea1.setFont(new java.awt.Font("Times New Roman", 1, 22)); // NOI18N
    jTextArea1.setLineWrap(true);
    jTextArea1.setRows(5);
    jTextArea1.setWrapStyleWord(true);
    jScrollPane1.setViewportView(jTextArea1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 974, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap())
    );

    pack();
}// </editor-fold>                        


public static void main(String args[]) {
new ScrollTextArea();
}

protected void scroll() {
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
    @Override
    protected Void doInBackground() throws Exception {
    for (int i = 0; i < 100; i++) {
        try {
        Thread.sleep(1000);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        jTextArea1.append(sentenceMap.get(i).toString() + "\n");
        publish(i);
    }
    return null;
    }

    @Override
    protected void process(List<Integer> chunks) {
    }

    @Override
    protected void done() {
    jTextArea1.append("Done");
    }
};
worker.execute();
}

// Variables declaration - do not modify                     
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration                   
}

This mechanism of auto-scroll relies on the cursor always being at the very end of the content of the text area. 这种自动滚动机制依赖于光标始终位于文本区域内容的最后。 For as long as the cursor is at the end, you have auto-scrolling. 只要光标位于末尾,您就可以自动滚动。 The moment the cursor goes anywhere else but the end, auto-scrolling ceases. 当光标移到终点以外的其他任何地方时,自动滚动都会停止。

So, in order to resume auto-scrolling, the only thing you need to do is move the cursor to the very end. 因此,为了恢复自动滚动,您唯一需要做的就是将光标移到最末端。 You can look for a way to do this programmatically, but until then you can just hit Ctrl+End when you want auto-scrolling to resume. 您可以寻找一种以编程方式执行此操作的方法,但在此之前,要恢复自动滚动时,只需Ctrl+End

Also please note that I found several warnings in your code, which means that you are programming without many useful warnings enabled, which tends to be very error-prone business. 另外请注意,我在您的代码中发现了几个警告,这意味着您在编程时未启用许多有用的警告,这往往是容易出错的业务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM