Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JTextArea仅在追加文本时滚动到底部_Java_Swing_Awt_Jscrollpane_Jtextarea - Fatal编程技术网

Java JTextArea仅在追加文本时滚动到底部

Java JTextArea仅在追加文本时滚动到底部,java,swing,awt,jscrollpane,jtextarea,Java,Swing,Awt,Jscrollpane,Jtextarea,我正在尝试创建一个JTextArea,每当文本附加到该文本区域时,它都会滚动到底部。否则,用户应该能够滚动到顶部并查看上一条消息。我使用了以下代码: JTextArea terminalText = new JTextArea(); JPanel terminal = new JPanel(); terminal.setLayout(new BorderLayout()); add(terminal); //Adds the terminal to mother JPanel //I a

我正在尝试创建一个
JTextArea
,每当文本附加到该文本区域时,它都会滚动到底部。否则,用户应该能够滚动到顶部并查看上一条消息。我使用了以下代码:

JTextArea terminalText  = new JTextArea();
JPanel terminal = new JPanel();
terminal.setLayout(new BorderLayout()); 
add(terminal);  //Adds the terminal to mother JPanel

//I added scrollbar to my JTextArea
JScrollPane scroll = new JScrollPane(terminalText);  
terminal.add(scroll, BorderLayout.CENTER);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

scroll.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
public void adjustmentValueChanged(AdjustmentEvent e) {  
 e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
}});
到目前为止,每当我使用
terminalText.append
terminalText
添加内容时,这段代码似乎都会使我的文本区域滚动到
terminalText
文本区域的底部

但是,用户不能使用滚动条滚动到顶部以查看上一条消息。有办法解决这个问题吗?我应该使用
DocumentListener
来实现这一点吗?

作为简单(粗略)的概念证明

这基本上会向
JTextArea
添加一个
DocumentListener
,在任何
Document
事件中,使用
setCaretPosition
将插入符号移动到文档的末尾

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.WeakHashMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JTextArea ta = new JTextArea(10, 20);
                ta.setWrapStyleWord(true);
                ta.setLineWrap(true);
                MoveToTheBottom.install(ta);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(ta));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Timer timer = new Timer(500, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        ta.append(new Date().toString() + "\n");
                    }
                });
                timer.start();
            }
        });
    }

    public static class MoveToTheBottom implements DocumentListener {

        private static WeakHashMap<JTextComponent, DocumentListener> registry = new WeakHashMap<>(25);
        private JTextComponent parent;

        protected MoveToTheBottom(JTextComponent parent) {
            this.parent = parent;
            parent.getDocument().addDocumentListener(this);
        }

        public static void install(JTextComponent parent) { 
            MoveToTheBottom bottom = new MoveToTheBottom(parent);
            registry.put(parent, bottom);
        }

        public static void uninstall(JTextComponent parent) {
            DocumentListener listener = registry.remove(parent);
            if (listener != null) {
                parent.getDocument().removeDocumentListener(listener);
            }
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

    }

}
导入java.awt.EventQueue;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.Date;
导入java.util.WeakHashMap;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.DocumentEvent;
导入javax.swing.event.DocumentListener;
导入javax.swing.text.JTextComponent;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JTextArea ta=新的JTextArea(10,20);
ta.setWrapStyleWord(真);
ta.setLineWrap(真);
移动到底部。安装(ta);
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新的JScrollPane(ta));
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
计时器计时器=新计时器(500,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
附加(新日期().toString()+“\n”);
}
});
timer.start();
}
});
}
公共静态类MoveToTheBottom实现DocumentListener{
私有静态WeakHashMap注册表=新WeakHashMap(25);
私有组件父级;
受保护的移动到底部(JTextComponent父级){
this.parent=parent;
parent.getDocument().addDocumentListener(此);
}
公共静态无效安装(JTextComponent父级){
移动到底部=新移动到底部(父级);
registry.put(父级,底部);
}
公共静态无效卸载(JTextComponent父级){
DocumentListener listener=registry.remove(父级);
if(侦听器!=null){
parent.getDocument().removeDocumentListener(listener);
}
}
@凌驾
公共作废插入更新(文档事件e){
setCaretPosition(例如getDocument().getLength());
}
@凌驾
公共作废移除更新(文档事件e){
setCaretPosition(例如getDocument().getLength());
}
@凌驾
公共作废更改日期(记录事件e){
setCaretPosition(例如getDocument().getLength());
}
}
}
该示例演示了一个可能的可重用API,您可以使用该API按要求“安装”和“卸载”支持,作为简单(粗略)的概念验证

这基本上会向
JTextArea
添加一个
DocumentListener
,在任何
Document
事件中,使用
setCaretPosition
将插入符号移动到文档的末尾

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.WeakHashMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JTextArea ta = new JTextArea(10, 20);
                ta.setWrapStyleWord(true);
                ta.setLineWrap(true);
                MoveToTheBottom.install(ta);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(ta));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Timer timer = new Timer(500, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        ta.append(new Date().toString() + "\n");
                    }
                });
                timer.start();
            }
        });
    }

    public static class MoveToTheBottom implements DocumentListener {

        private static WeakHashMap<JTextComponent, DocumentListener> registry = new WeakHashMap<>(25);
        private JTextComponent parent;

        protected MoveToTheBottom(JTextComponent parent) {
            this.parent = parent;
            parent.getDocument().addDocumentListener(this);
        }

        public static void install(JTextComponent parent) { 
            MoveToTheBottom bottom = new MoveToTheBottom(parent);
            registry.put(parent, bottom);
        }

        public static void uninstall(JTextComponent parent) {
            DocumentListener listener = registry.remove(parent);
            if (listener != null) {
                parent.getDocument().removeDocumentListener(listener);
            }
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            parent.setCaretPosition(e.getDocument().getLength());
        }

    }

}
导入java.awt.EventQueue;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.Date;
导入java.util.WeakHashMap;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.DocumentEvent;
导入javax.swing.event.DocumentListener;
导入javax.swing.text.JTextComponent;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JTextArea ta=新的JTextArea(10,20);
ta.setWrapStyleWord(真);
ta.setLineWrap(真);
移动到底部。安装(ta);
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新的JScrollPane(ta));
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
计时器计时器=新计时器(500,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){