我有一个JScrollPane
和一个JTextArea
(可编辑),有10行。我希望第一个用户输入显示在JTextArea
的底部,最近的输入应该向上推送前一个输入。要实现这一点,我使用textArea.setMargin(new Insets(x,0,0,0));
并且一切正常 - 除了我的第二个输入将切换JScrollPane
。
如何从JTextArea
的底部开始,只在整个原始视口填充时启用滚动?
答案 0 :(得分:2)
基本上,您可以将JTextText
添加到JPanel
上,其他JPanel
作为填充符,使JTextArea
占用实际需要的最小空间。< / p>
我是通过使用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);
}
}
}
答案 1 :(得分:1)
为了达到这个目的,我使用textArea.setMargin(new Insets(x,0,0,0));并且一切正常 - 除了我的第二个输入将切换JScrollPane。
我猜想每次向文本区域添加文本时都需要重置边距,以考虑与滚动窗格大小相关的文本区域的新首选大小。
您应该能够将DocumentListener添加到文本区域,并在文档添加到文档时进行调整。
答案 2 :(得分:1)
我认为使用边距和插图是不可取的,因为您正在使用布局调整来实现文本(内容)功能。这应该由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个空行。我也不确定你在文本区域可以做什么。此解决方案假设您不能跳线,并且每次插入一行时它都不是空白,而是在前一行之后。