Java Tips Weblog

  • Blog Stats

    • 2,571,659 hits
  • Categories

  • Archives

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);

message-console

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.

Get The Code

MessageConsole.java

See Also

Limit Lines in Document

42 Responses to “Message Console”

  1. Keith Corlett said

    Your blog is just full of useful suprises. Thanks for the fish!

    Cheers. Keith.

  2. 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

  3. rniamo said

    which licence ?

  4. 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!

  5. 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 :)

  6. 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?

  7. 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).

  8. 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!

  9. teo said

    thank you thank you thank you very much!

  10. Anonymous said

    Thanks a lot!!

  11. 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.

      private void initGUI() 
      {
      	setPreferredSize(new Dimension(800, 600));
      	final MigLayout migLayout = new MigLayout();
      	setLayout(migLayout);
      	final JTextArea jTextArea = new JTextArea(5, 100);
      	add(new JScrollPane(jTextArea));
      	final MessageConsole messageConsole = new MessageConsole(jTextArea);
      	messageConsole.redirectOut();
      	messageConsole.setMessageLines(100);
      	System.err.println("Hi");
      
      	{
      		final Layout layout = new TTCCLayout("yyyy-MM-dd HH:mm:ss");
      		final ConsoleAppender appender = new ConsoleAppender();
      		appender.setName(ConsoleAppender.class.getSimpleName());
      		appender.setLayout(layout);
      		appender.activateOptions();
      		Logger.getRootLogger().addAppender(appender);
      	}
      
      	final Logger logger = Logger.getRootLogger();
      	logger.info("Hello, World!");
      }
      
  12. Anonymous said

    very nice!

  13. Anonymous said

    this is great, but what exactly is textComponent?

  14. 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.

  15. 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

  16. 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 ?

  17. Flavio said

    Very very nice!!!! Thanks

  18. 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.

  19. 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!!

  20. Art said

    Thank you very much

  21. 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.

Leave a comment