I am developing a GUI with a JTextArea
to show certain messages. Two kind of messages might appear here: those written on purpose and intended for the user ("Task completed", "No file found", "Please wait"...) and those for the developer (information about exceptions, warnings, help messages...).
- So far, I am considering two options to show information on the
JTextArea
: use the setText()
method, or use System.out.print()
and redirect the output stream to the JTextArea
.
Which option is better? Why?
- How can I implement a system to allow the user to select which kind
of messages are to be showed on the JTextArea
? Something like a JComboBox
with different options, so the User can select if he/she wants to get just Application Messages, or messages related to the workflow (warnings, exceptions, etc.)
If you don't want use to an extra logging library (if the program is small, or if you have to save space (for example in an applet)...), you can always use the logging in JSE: java.util.logging.
If so, you can use a Handler to write to the text component:
final class TextComponentHandler extends Handler {
@Nonnull private final JTextArea text;
TextComponentHandler(@Nonnull JTextArea text) {
this.text = text;
}
@Override
public void publish(LogRecord record) {
if (isLoggable(record))
synchronized(text) {
text.append(getFormatter().format(record));
}
}
@Override
public void flush() {/**/}
@Override
public void close() throws SecurityException {/**/}
}
and add it with:
JTextArea textArea = new JTextArea() {
@Override
public void addNotify() {
super.addNotify();
for(Handler hh : logger.getHandlers())
if (hh == h)
return;
logger.addHandler(h);
}
@Override
public void removeNotify() {
super.removeNotify();
logger.removeHandler(h);
}
};
Logger logger = Logger.getLogger("my.logger");
Handler h = new TextComponentHandler(textArea);
logger.addHandler(h);
- I would just use
setText()
. Using System.out.println()
and redirecting to the JTextArea
would make things needlessly more complex.
- If you have a component that collects messages (which are then displayed by the
JTextArea
), you could change it so you do not only supply a message but also something like a Category
. Depending on the content of the JComboBox
, only messages of a certain Category
would be displayed inside the JTextArea
.
If I may suggest a somewhat different approach: maybe you're using something like Log4J or Logback inside your application to log messages. It might well be able to register a custom appender for your logging framework that redirects to the JTextArea
. This approach might be a bit more work to get it running, but it could allow for greater flexibility - and not re-inventing a wheel that already exists.
My two cents on how to do this would be to have something like a FeedbackManager
(I just made up the name, so feel free to make up a better name). This FeedbackManager
would be a singleton, all classes that use it would refer to the same instance. Whenever you need to present a message to the user, post it to the FeedbackManager
, including the Category
(see above). When the FeedbackManager
receives a Message
, it should inform all its listeners that a new message was posted.
When instantiating the JTextArea
, register an anonymous listener to the FeedbackManager
; when the listener is called, it can check whether the message must be displayed based on the selection of the JComboBox
, and if so, append it to the JTextArea
.