Java 在JTextArea的底部写入

Java 在JTextArea的底部写入,java,swing,jscrollpane,jtextarea,Java,Swing,Jscrollpane,Jtextarea,我有一个JScrollPane和一个JTextArea(可编辑)有10行。我希望第一个用户输入出现在JTextArea的底部,最近的输入应该向上推前一个输入。为了实现这一点,我使用textArea.setMargin(新的Insets(x,0,0,0))一切都正常工作-除了我的第二次输入将切换JScrollPane 如何从JTextArea的底部开始,并且仅在整个原始视口被填充时才启用滚动 基本上,您可以将JTextText添加到JPanel上,另一个JPanel充当填充物,使JTextArea

我有一个
JScrollPane
和一个
JTextArea
(可编辑)有10行。我希望第一个用户输入出现在
JTextArea
的底部,最近的输入应该向上推前一个输入。为了实现这一点,我使用
textArea.setMargin(新的Insets(x,0,0,0))一切都正常工作-除了我的第二次输入将切换
JScrollPane

如何从
JTextArea
的底部开始,并且仅在整个原始视口被填充时才启用滚动


基本上,您可以将
JTextText
添加到
JPanel
上,另一个
JPanel
充当填充物,使
JTextArea
占据它实际需要的最小空间

我通过使用
GridBagLayout
强制填充占据它所能占据的大部分空间来实现这一点

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestTextArea {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(new TestPane()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            JPanel filler = new JPanel();
            filler.setBackground(Color.WHITE);
            add(filler, gbc);

            gbc.gridy = 1;
            gbc.weighty = 0;
            ta = new JTextArea(1, 20);
            add(ta, gbc);
        }
    }

}


基本上,您可以将
JTextText
添加到
JPanel
上,使用另一个
JPanel
作为填充,从而使
JTextArea
占据实际需要的最小空间

我通过使用
GridBagLayout
强制填充占据它所能占据的大部分空间来实现这一点

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestTextArea {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(new TestPane()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            JPanel filler = new JPanel();
            filler.setBackground(Color.WHITE);
            add(filler, gbc);

            gbc.gridy = 1;
            gbc.weighty = 0;
            ta = new JTextArea(1, 20);
            add(ta, gbc);
        }
    }

}

为了实现这一点,我使用textArea.setMargin(新的Insets(x,0,0,0));一切都正常工作——除了我的第二个输入将切换JScrollPane

我猜,每次向文本区域添加文本时,您都需要重置边距,以考虑文本区域相对于滚动窗格大小的新首选大小

您应该能够向文本区域添加DocumentListener,并在向文档添加文本时进行调整

为了实现这一点,我使用textArea.setMargin(新的Insets(x,0,0,0));一切都正常工作——除了我的第二个输入将切换JScrollPane

我猜,每次向文本区域添加文本时,您都需要重置边距,以考虑文本区域相对于滚动窗格大小的新首选大小


您应该能够向文本区域添加DocumentListener,并在向文档添加文本时进行调整

我不认为使用页边距和插图是可行的,因为您正在使用布局调整来实现文本(内容)功能。这应该由
Document
对象控制,该对象是
JTextArea
就其内容调用的对象

如果您在内部调用
append
,则在扩展JTextArea的新类中重写它:

public class Test {

static MyTextArea ta = new MyTextArea();
static int x = 0;

    public static void main(String[] args) {

        ta.setRows(10);
        ta.setText("\n\n\n\n\n\n\n\n\n");
        ta.setCaretPosition(ta.getDocument().getLength());

        JButton append = new JButton("Append");
        append.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ta.append("\n" + x);
                x++;
            }
        });

        JFrame frame= new JFrame();
        frame.setContentPane(new JPanel(new BorderLayout()));
        frame.getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER);
        frame.getContentPane().add(append, BorderLayout.LINE_START);

        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    static class MyTextArea extends JTextArea {

        @Override
        public void append(String str) {

            super.append(str);
            try {
                if (getDocument().getText(0, 1).equals("\n"))
                    getDocument().remove(0, 1);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
        }
    }
}
如果要手动编辑,请添加DocumentListener:

public class Test {

    public static void main(String[] args) {

        JTextArea ta = new JTextArea();
        ta.setRows(10);
        ta.setText("\n\n\n\n\n\n\n\n\n");
        ta.setCaretPosition(ta.getDocument().getLength());
        ta.getDocument().addDocumentListener(new MyDocListener());

        JFrame frame= new JFrame();
        frame.setContentPane(new JPanel(new BorderLayout()));
        frame.getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER);

        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    static class MyDocListener implements DocumentListener {

        @Override
        public void insertUpdate(DocumentEvent e) {

            final DocumentEvent de = e;

            Runnable pushUp = new Runnable() {

                @Override
                public void run() {

                    String t = null;
                    try {
                        t = de.getDocument().getText(de.getOffset(), de.getLength());
                        if (t.equals("\n") && de.getDocument().getText(0, 1).equals("\n"))
                            ta.getDocument().remove(0, 1);
                    } catch (BadLocationException e1) {
                        e1.printStackTrace();
                    }
                }
            };       
            SwingUtilities.invokeLater(pushUp);     
        }

        @Override
        public void removeUpdate(DocumentEvent e) {}

        @Override
        public void changedUpdate(DocumentEvent e) {}
    }
}

请注意,代码中需要的只是内部类,其余的只是为了让您看到它的工作情况。我也没有关于文本区域初始状态的信息。在这里,我只是将行数设置为10,将文本设置为10个空行。我也不确定你在文本区可以做什么。此解决方案假设您不能跳行,并且每次插入一行时,它都不是空的,并且跟随前一行。

我不认为使用边距和插入是一种方法,因为您使用布局调整来实现文本(内容)功能。这应该由
Document
对象控制,该对象是
JTextArea
就其内容调用的对象

如果您在内部调用
append
,则在扩展JTextArea的新类中重写它:

public class Test {

static MyTextArea ta = new MyTextArea();
static int x = 0;

    public static void main(String[] args) {

        ta.setRows(10);
        ta.setText("\n\n\n\n\n\n\n\n\n");
        ta.setCaretPosition(ta.getDocument().getLength());

        JButton append = new JButton("Append");
        append.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ta.append("\n" + x);
                x++;
            }
        });

        JFrame frame= new JFrame();
        frame.setContentPane(new JPanel(new BorderLayout()));
        frame.getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER);
        frame.getContentPane().add(append, BorderLayout.LINE_START);

        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    static class MyTextArea extends JTextArea {

        @Override
        public void append(String str) {

            super.append(str);
            try {
                if (getDocument().getText(0, 1).equals("\n"))
                    getDocument().remove(0, 1);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
        }
    }
}
如果要手动编辑,请添加DocumentListener:

public class Test {

    public static void main(String[] args) {

        JTextArea ta = new JTextArea();
        ta.setRows(10);
        ta.setText("\n\n\n\n\n\n\n\n\n");
        ta.setCaretPosition(ta.getDocument().getLength());
        ta.getDocument().addDocumentListener(new MyDocListener());

        JFrame frame= new JFrame();
        frame.setContentPane(new JPanel(new BorderLayout()));
        frame.getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER);

        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    static class MyDocListener implements DocumentListener {

        @Override
        public void insertUpdate(DocumentEvent e) {

            final DocumentEvent de = e;

            Runnable pushUp = new Runnable() {

                @Override
                public void run() {

                    String t = null;
                    try {
                        t = de.getDocument().getText(de.getOffset(), de.getLength());
                        if (t.equals("\n") && de.getDocument().getText(0, 1).equals("\n"))
                            ta.getDocument().remove(0, 1);
                    } catch (BadLocationException e1) {
                        e1.printStackTrace();
                    }
                }
            };       
            SwingUtilities.invokeLater(pushUp);     
        }

        @Override
        public void removeUpdate(DocumentEvent e) {}

        @Override
        public void changedUpdate(DocumentEvent e) {}
    }
}

请注意,代码中需要的只是内部类,其余的只是为了让您看到它的工作情况。我也没有关于文本区域初始状态的信息。在这里,我只是将行数设置为10,将文本设置为10个空行。我也不确定你在文本区可以做什么。此解决方案假设您不能跳行,并且每次插入一行时,它都不是空的,并且会跟随前一行。

我没有足够的内容继续。你能详细说明一下吗?你知道我输入的最后几行已经是可见的了。这只是JScLangPad的即时切换使我不舒服。@ USER 2651804也许你应该考虑提供,所以我们都在同一个页面。这里有两个屏幕显示应该说明我的问题:并且不知道是否操纵插入符号是答案还是不,但是不要使用不使用TexTaRea. GETTrk()。因为这是没有效率的,因为需要解析文档以创建文本字符串。相反,您可以只使用
textArea.getDocument().getLength()
@user2651804,如果你想让其他人帮忙,图片应该是问题的一部分,而不是评论,这样每个人都可以看到这些图片。@camickr有一次有人责骂我,因为我在问题中发布了视频。我不知道如何把它作为一个真实的图片发布,哈哈。我没有足够的东西继续。你能详细说明一下吗?你知道我输入的最后几行已经是可见的了。这只是JScLangPad的即时切换使我不舒服。@ USER 2651804也许你应该考虑提供,所以我们都在同一个页面。这里有两个屏幕显示应该说明我的问题:并且不知道是否操纵插入符号是答案还是不,但是不要使用不使用TexTaRea. GETTrk()。因为这是没有效率的,因为需要解析文档以创建文本字符串。相反,您可以只使用
textArea.getDocument().getLength()
@user2651804,如果你想让其他人帮忙,图片应该是问题的一部分,而不是评论,这样每个人都可以看到这些图片。@camickr有一次有人责骂我,因为我在问题中发布了视频。我不知道如何把它贴成一张真实的图片,哈哈。我有两个问题:1)我