在Jtextpane(与在Jscrollpane),每当我们输入文本,它将从上到下打印,
是否可以将滚动条保持在底部,并在添加文本时向上移动旧文本(启用滚动条)?
e。g:如果用户在第一行,输入"xyz"并按ENTER。滚动条应该启用,xyz应该向上移动,在第二行使用插入符号。因此,如果用户向上滚动,他将能够看到"xyz"。
这个问题和我以前的问题很相似。我想说清楚,想得到一个答案。谢谢。
编辑
public class TextPane extends JFrame implements ActionListener, KeyListener{
public static TextPane instance;
private static JTextPane terminal = new JTextPane();
private static JScrollPane scroll = new JScrollPane();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
TextPane.getInstance().init();
}
});
}
private static TextPane getInstance() {
if(null == instance){
instance = new TextPane();
}
return instance;
}
private EnterAction enterAction;
private void init() {
terminal.setFont(new Font("Courier new", Font.PLAIN, 12));
terminal.setLayout(new BorderLayout());
terminal.setBackground(Color.black);
terminal.setForeground(Color.white);
terminal.addKeyListener(this);
terminal.setCaretColor(Color.green);
terminal.setDragEnabled(false);
enterAction = new EnterAction();
terminal.getInputMap().put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter");
terminal.getActionMap().put("enter", enterAction);
DefaultCaret caret = (DefaultCaret) terminal.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
scroll.setViewportView(terminal);
add(scroll);
setTitle("Dummy");
setSize(500 , 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
}
class EnterAction extends AbstractAction {
//I typed a single line (in first line) of text and pressed enter.
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ae ) {
try {
Document doc = terminal.getDocument();
int car = terminal.getCaretPosition();
//Currently i tried adding newlines to get scroll bar in order to hide previously displayed contents.
for(int i=0 ; i< 35 ; i++){
doc.insertString(doc.getLength(), "n", null);
}
terminal.setCaretPosition(car + 1); // To set the caret at second line.
JScrollBar sb = scroll.getVerticalScrollBar();
sb.setValue( sb.getMaximum());//to keep the scroll bar at bottom.(Any how above setCaretPositon() makes it not work).
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
@Override
public void actionPerformed(ActionEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
}
我认为这是你想要的。一些笔记:
- 与您的示例一样,代码使用空行填充文档。虽然在这个例子中,这些行只在创建文本组件时添加一次。
-
invokeLater
在EnterAction中用于将代码添加到事件调度线程的末尾。这确保了文档的所有更新都已完成,因此滚动条的最大值将是正确的。 我使用了JTextArea,因为它很容易根据初始化文本区域所需的空白行数来控制文本区域的大小。如果你使用JTextPane,那么你将需要做额外的计算来确定文本窗格的实际大小,以便滚动条正确工作。作为奖励,我创建了一个简单的NavigationFilter,它将防止用户将插入符号移动到文档末尾的任何空白行。此功能还将阻止使用鼠标选择任何空白行。 - 仍然可以删除空行。所以你可能想要创建一个KeyBinding,当按下"Delete"键时不做任何事情。 重写框架宽度的代码只是为了防止第一次在文本窗格中输入任何数据时出现水平滚动条。您可能需要考虑始终显示滚动条,因为无论如何,在添加第一行数据后,它将持续可见。
代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class NavigationFilterSuffix extends NavigationFilter
{
private int suffixLength;
private Document doc;
public NavigationFilterSuffix(int suffixLength, Document doc)
{
this.suffixLength = suffixLength;
System.out.println(suffixLength);
this.doc = doc;
}
public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
int endOfDocument = doc.getLength() - suffixLength + 1;
fb.setDot(Math.min(dot, endOfDocument), bias);
}
public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
{
int endOfDocument = doc.getLength() - suffixLength + 1;
fb.moveDot(Math.min(dot, endOfDocument), bias);
}
public static void main(String args[]) throws Exception
{
final JTextArea terminal = new JTextArea(15, 30);
// add 14 new lines (one less than rows specified above
terminal.setText("nnnnnnnnnnnnnn");
terminal.setFont(new Font("Courier new", Font.PLAIN, 12));
terminal.setBackground(Color.black);
terminal.setForeground(Color.white);
terminal.setCaretColor(Color.green);
terminal.setDragEnabled(false);
terminal.setCaretPosition(0);
final JScrollPane scrollPane = new JScrollPane( terminal );
Action enterAction = new EnterAction();
terminal.getInputMap().put( KeyStroke.getKeyStroke("ENTER"), "enter");
terminal.getActionMap().put("enter", enterAction);
terminal.setNavigationFilter(new NavigationFilterSuffix(terminal.getRows(), terminal.getDocument()));
JFrame frame = new JFrame("Navigation Filter Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
Dimension d = frame.getSize();
d.width += 20;
frame.setSize(d);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
static class EnterAction extends AbstractAction
{
public void actionPerformed(ActionEvent ae )
{
try
{
final JTextArea terminal = (JTextArea)ae.getSource();
Document doc = terminal.getDocument();
int car = terminal.getCaretPosition();
doc.insertString(car, "n", null);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JScrollPane scrollPane = (JScrollPane)SwingUtilities.getAncestorOfClass(JScrollPane.class, terminal);
JScrollBar sb = scrollPane.getVerticalScrollBar();
sb.setValue( sb.getMaximum());
}
});
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}
好运。
根据上面的对话的示例代码。请检查这是否满足您的目的。
public class ThingDoer extends JPanel {
public ThingDoer() {
JTextArea text = new JTextArea(1, 10);
text.setLineWrap(true);
text.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(text,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
add(scrollPane);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new ThingDoer());
frame.pack();
frame.setSize(200, 300);
frame.setVisible(true);
}
}