My problem is that the JTextArea
with JScrollPane
added is not scrolling to the newest line printed (the scroll bar stays at the top).
The caveat is that lines are printed in the separate SwingWorker
thread.
Whereas, if I get rid of SwingWorker
in the simulation()
, the scrolling seems to be working fine.
Can someone please give me a hint how to cope with this?
Here is the code I am testing on (import
s omitted):
public class Test4 {
private JFrame frame;
private JTextArea textArea;
private JButton btnNewButton;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test4 window = new Test4();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Test4() throws InterruptedException {
initialize();
}
private void initialize() throws InterruptedException {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scroll = new JScrollPane(textArea);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
btnNewButton = new JButton("Test Scrolling");
frame.getContentPane().add(btnNewButton, BorderLayout.NORTH);
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
simulation();
}
});
}
private void simulation() {
SwingWorker<Void, Void> swingWorker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
TestOutputStream customOutputStream = new TestOutputStream(
textArea);
System.setOut(new PrintStream(customOutputStream, true, "UTF-8"));
for (int i = 0; i < 30; i++) {
System.out.println("TEST");
}
return null;
}
};
swingWorker.execute();
}
}
class TestOutputStream extends OutputStream {
private final ByteArrayOutputStream buf = new ByteArrayOutputStream();
private final JTextArea consoleOutput;
public TestOutputStream(JTextArea consoleOutput) {
super();
this.consoleOutput = consoleOutput;
}
@Override
public void flush() throws IOException {
consoleOutput.append(buf.toString("UTF-8"));
buf.reset();
}
@Override
public void write(int b) throws IOException {
buf.write(b);
}
}
Here is the code I am testing on (imports omitted):
Why? Post code that we can copy/paste/test. I don't use an IDE and should not have to spend the time to enter the imports.
Your code didn't do anything when I tested it. I'm using JDK8 on Windows 7.
I had to add the following after your loop in the SwingWorker:
customOutputStream.flush();
is not scrolling to the newest line printed (the scroll bar stays at the top).
It doesn't scroll because the text is not appended to the text area on the EDT.
JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
The above code worked for me.
Check out Text Area Scrolling for more information on this problem.