In a Jtextpane(with in a Jscrollpane) whenever we enter text it will be printed from top to bottom,
is it possible to keep the scroll bar at the bottom and move old text upwards(enabling scrollbar) whenever a text is appended?
e.g : if user is at line 1 and types "xyz" and press ENTER . Scrollbar should be enabled and xyz should be moved upwards with caret at second line.So if user scrolls up he will be able to see "xyz".
The problem is similar to my previous questions. I am trying to make it clear to get an answer.
Thanks.
EDIT
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) {}
}
I think this is what you want. Some notes:
invokeLater
is used in the EnterAction to add the code to the end of the Event Dispatch Thread. This makes sure that all updates to the Document have been completed and therefore the maximum value of the scrollbar will be correct.The Code:
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("\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
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();
}
}
}
}
Good luck.