Message Console
Posted by Rob Camick on November 8, 2008
There may be times when you want to capture output from your program and display it for the user. This is generally done by creating a console. Using Swing it is not too difficult to create a simple console using a JTextArea or JTextPane. Our message console will be able to display output written to System.out and System.err.
The MessageConsole class will enable you to use a text area or text pane as a simple console. First you must decide which component to use:
- JTextArea – will be more efficient
- JTextPane – will allow you to color the text from each source
Next you must decide how you want the console to function:
- append – messages will be added to the bottom of the console
- insert – messages will be inserted as the first line of the console
Finally, you need to decide if you need to limit the number of lines contained in the console. The MessageConsole will use my LimitLinesDocumentListener described in an earlier blog entry.
So the code for a simple useage of this class might be something like:
somePanel.add( new JScrollPane( textComponent ) );
MessageConsole mc = new MessageConsole(textComponent);
mc.redirectOut();
mc.redirectErr(Color.RED, null);
mc.setMessageLines(100);
One last comment. You can optionally redirect the message to a PrintStream. So if you did something like the following:
mc.redirectOut(null, System.out);
The message would display in your message console as well as the normal output console.
Keith Corlett said
Your blog is just full of useful suprises. Thanks for the fish!
Cheers. Keith.
Rob Camick said
Glad you found the fishing good!
Sven Goetgeluck said
Hi,
thanks for sharing this wonderfull code, but i was wondering if it was possible to embed this in sort of dropdownbox ( saw this on the lotus notes console) were u see 1 line at a time and when opening you spot fe te 10 last lines, did u ever make this?
with regards
Sven
rniamo said
which licence ?
Rob Camick said
No licence. The “About” page mentions this issue.
Kylex said
How do you deal with the synchronization needed?
I didn’t test your solution but as far as I looked into your code, the Document.remove is not in synch with your JTextArea.setCaretPosition, that could cause a problem since Document.getLength() could return a value X and just after that the length of the document is modified by your LimitLineDocumentListener so the actual value would be Y = X – Z . Whereas JTextArea.setCaretPosition(X) is of course not valid anymore.
Did I overlook sth. here or is this a problem of your current solution?
Could ofcourse be easily fixed with a lock on the document which both share.
Beside of that: Looks good & useful!
Philip Gamble said
Very useful thanks for posting this. I found a few other snippits of code online but none that worked as well as yours across multiple classes and it was easy to integrate into my program :)
brunez said
Thanks for this, it works fine.
But, is it possible to print the info in the console while the application is busy?
I’ve written a program that searches files, and I’d like to print the completed percentage while it’s at it, but it only prints the information when it’s done, which is obviously not very useful.
Is there any way to have it print info during the task?
Rob Camick said
You need to execute your long running task on a separate Thread so the GUI remains responsive and can repaint itself.
Varun said
I tried to run the Swing Message Console on a separate thread but could not get it to work. I was reading somewhere that Swing utilities do not work the same way in multithreaded environment. Is that the reason?
Thomas said
I’m having some issues with the way I’ve implemented this code.
I added the MessageConsole class to my project and initialized it in the EDT. I have several background tasks which output messages just fine, but if I use System.out within the main thread the text will fail to update in the TextPane. I’m guessing the EDT is blocking it, but I’m not sure how to fix it. Run all messages from the main thread as tasks, even if it’s just to send a message to the TextPane?
Thanks,
Tom
Rob Camick said
I don’t understand why you would have problems using System.out.println() in the main thread. Maybe if you post an SSCCE by using the “Contact Us” page I can see what is happening.
Thomas said
I figured it out. It has to do with the fact that I am using my own spacing (sometimes I would want a \n to separate textual output). Running a method twice that has the following code:
System.out.println(“This will work!”);
System.out.println(“This doesn’t work!” + “\n”);
would print:
This will work!
This doesn’t work!
This will work!
Whereas running a method twice with the order reversed:
System.out.println(“This doesn’t work!” + “\n”);
System.out.println(“This will work!”);
would print:
This doesn’t work!
This will work!
This doesn’t work!
This will work!
So, as in the first example, it seems the \n is holding up the buffer. Nothing that can’t be fixed with a little modification to the MessageConsole code, but it was something I initially overlooked.
Greg M. said
Hi Tom,
I use MessageConsole and have some problem with a MessageConsole and a background task that write on System.out/err : the application block when write some line.
> Nothing that can’t be fixed with a little modification to the MessageConsole code
Perhaps your fix on MessageConsole could help me ?
Rob Camick said
I just fixed a problem that occurred when the message contained a “\n” at the end of the message (as noted by Thomas). In these cases the message was just stored in the buffer and never added to the text pane.
Greg M. said
Thanks for the reply.
I try your updated code, but it’s the same problem.
It seems it’s the LimitLinesDocumentListener that blocks (when I remove setMessageLines(…) option, it work well).
Jeremy said
This is fantastic. The code certainly provided me with the information I need to implement my processing display logic. GUI has never been my strong suite but this code is very clear, well written, and well commented. Thank you for providing this code and explanation!
Rob Camick said
Thanks for the feedback.
teo said
thank you thank you thank you very much!
Rob Camick said
Glad you found a couple of topics that you can use.
Anonymous said
Thanks a lot!!
Anonymous said
Hi,
Can you please tell me how we can print the log4j logs with the same code which you have provided?
Right now I can see only the System.out and System.err are getting printed in the textarea but not the log4j logs. Any help?
Jack said
Try this please.
Anonymous said
Thanks again :)
Anonymous said
very nice!
Anonymous said
this is great, but what exactly is textComponent?
Rob Camick said
A JTextArea or JTextPane.
Waleed Shabbir said
hey there
mc.redirectErr(Color.RED, null);
is not working. Errors are being shown in default black color .
and one more thing how can i clear console in GUI ?
Rob Camick said
You need to invoke System.err.println(…) to generate and error message.
Waleed Shabbir said
could you please tell me how? i am having difficulty in understanding it.
Waleed Shabbir said
error messages are being generated but not in the red color. that was my question
Rob Camick said
You need to use a JTextPane to display messages of a different color. If this doesn’t help then post your code that demonstrates the problem. That is create a JFrame. Add the JTextPane to the frame. Use the MessageConsole class on the text pane. Then invoke System.out.println(…) and System.err.println(…) to see the difference.
Marian said
Hey,
I reused your message console for an extension and made it public on GitHub:
https://github.com/zaplatynski/second-hand-log
Thanks!
Marian
john said
hey i used your messageconsole class in my project. I am using exceptionhandling and displaying message . how can i pass arguement to this class to show or append text ?
Rob Camick said
The class is designed to display text when you use System.out.println().
john said
is there any way in which i can implement .getmessage() ?
john said
hey i have done it by by using System.out.println().
thnx alot :)
Flavio said
Very very nice!!!! Thanks
Gerry Howser said
Excuse the simplicity of my question, but could you post a short, full example using this? I have a need for this constantly but SWING is not my strong suite.
MA said
The code is working fine for me without JScrollPane. But if I add code for JScrollPane, the component (JTextArea) is not displayed on the Frame. Please help!!
Art said
Thank you very much
Luis said
as I can show in a JTextArea the logs log4j while the program is running, I would like it to be the complete code since I am new in this logs theme.