I want to have a JTextArea that can completely work instead of a console but I don't know how to do this!
Thank you
The solution to the problem is to redirect System.{in,out,err}
to a JTextArea
.
Starting with System.out
it's pretty straight forward to to redirect it to your JTextArea
component using System.setOut
method. In the example below I've done this using pipes and SwingWorker
but that is all fancy stuff to actually get the output simpler to the swing component.
Emulating System.in
is simular, you need to redirect your keystrokes to the the System.in
using System.setIn
. Again, in the example below, I've used pipes to get a nicer interface. I also buffer the line (just like a "normal" console would do) till you hit enter. (Note that for example arrow keys will not work but it shouldn't be to much work to get it also to be handled/ignored.)
The text in the screenshot below was produced by a number of calls to the "normal" System.out.print..
method and then waiting for input on System.in
using a Scanner
:
public static JTextArea console(final InputStream out, final PrintWriter in) {
final JTextArea area = new JTextArea();
// handle "System.out"
new SwingWorker<Void, String>() {
@Override protected Void doInBackground() throws Exception {
Scanner s = new Scanner(out);
while (s.hasNextLine()) publish(s.nextLine() + "\n");
return null;
}
@Override protected void process(List<String> chunks) {
for (String line : chunks) area.append(line);
}
}.execute();
// handle "System.in"
area.addKeyListener(new KeyAdapter() {
private StringBuffer line = new StringBuffer();
@Override public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (c == KeyEvent.VK_ENTER) {
in.println(line);
line.setLength(0);
} else if (c == KeyEvent.VK_BACK_SPACE) {
line.setLength(line.length() - 1);
} else if (!Character.isISOControl(c)) {
line.append(e.getKeyChar());
}
}
});
return area;
}
And the example main
method:
public static void main(String[] args) throws IOException {
// 1. create the pipes
PipedInputStream inPipe = new PipedInputStream();
PipedInputStream outPipe = new PipedInputStream();
// 2. set the System.in and System.out streams
System.setIn(inPipe);
System.setOut(new PrintStream(new PipedOutputStream(outPipe), true));
PrintWriter inWriter = new PrintWriter(new PipedOutputStream(inPipe), true);
// 3. create the gui
JFrame frame = new JFrame("\"Console\"");
frame.add(console(outPipe, inWriter));
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// 4. write some output (to JTextArea)
System.out.println("Hello World!");
System.out.println("Test");
System.out.println("Test");
System.out.println("Test");
// 5. get some input (from JTextArea)
Scanner s = new Scanner(System.in);
System.out.printf("got from input: \"%s\"%n", s.nextLine());
}