Reputation: 25755
I'm currently trying to make Log4J log into a JTextPane
. I want to use a TextPane because I want basic highlighting (e.g. errors are red and infos are green).
I have two loggers set up, one (the root-logger) logs everything into a file and the other (guiLogger
) logs only some errors and infos on the GUI in a JTextPane
.
The problem I'm currently facing is, that I can't get appending to the TextPane to work. What I currently have looks something like this:
public class Log extends AppenderSkeleton{
private final JTextPane log;
private final StyledDocument doc;
public Log(){
super();
log = new JTextPane();
doc = log.getStyledDocument();
}
@Override
protected void append(LoggingEvent loggingEvent) {
try {
doc.insertString(doc.getLength(), "Hello World!", null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public JTextPane getView(){
return log;
}
}
The Log4J config-file looks like this:
# The root-logger should log everything.
log4j.rootLogger = DEBUG, file
# Append the logs to a file.
log4j.appender.file = org.apache.log4j.RollingFileAppender
# [...]
# The logger which logs on the GUI (just some user-information).
log4j.logger.guiLogger = INFO, gui
# Append the logs to the GUI
log4j.appender.gui = mypackage.Log
# Formatting of the output:
log4j.appender.gui.layout = org.apache.log4j.PatternLayout
log4j.appender.gui.layout.ConversionPattern = %m%n
The append()
-method gets called, and the insertString()
-method performs clean (it does not enter the catch
-block), but I don't see any content in the TextPane on the GUI.
What I have tried to fix this:
insertString()
-method using SwingUtilities.invokeLater()
insertString()
-method from a SwingWorker
validate()
, revalidate()
and repaint()
on the JTextPane
StyledDocument
-object but directly getting it from the log
-instance: log.getStyledDocument().insertString(0, "Hello World!", info_log);
setText()
-method of the JTextPane
(only works in the constructor).Since the JTextPane
has no fireContentChanged()
-method (or similar), I'm kind of lost here.
I have played around a bit more and found some other things:
StyledDocument
gets updated (calling getText()
shows that the text has been inserted).append()
or insertString()
-method directly from the compiler (after initializing the StyledDocument
and the JTextPane
), it all works fine.Also, I checked which thread called the method by adding this to the append()
-method body:
System.out.println("Thread: "+Thread.currentThread().getName());
It shows the following if I simply do two log-statements from somewhere in the code:
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
and when I call the append()
-method directly from the constructor of the Log
-class (plus the two logging-statements from above), it shows the following:
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
The first call appends the text probably. But the other two don't seam to work.
My GUI is build from the AWT-EventQueue
by using SwingUtilities.invokeLater()
. The two logging-calls are made in the same context (and therefore come from the EventQueue, too).
Upvotes: 2
Views: 2283
Reputation: 691785
The text pane is private to the appender, and you don't have any getter for it. So I would guess that the GUI has a text pane, and the logger has another text pane it appends to.
That, or you're getting the text pane from a Log instance that is not the same as the Log instance that Log4j instantiates.
Also, the appender might be use by several threads, but the Swing components may only be accessed from the event dispatch thread. Every append to the text pane should be done inside a SwingUtilities.invokeLater()
call.
Upvotes: 2
Reputation: 57391
Check whether yu don;t call setText() or setContentType() and may be some more methods which recreate Document. Instead of saving reference to the document get it from pane. Not
doc.insertString(doc.getLength(), "Hello World!", null);
but
log.getStyledDocument().insertString(doc.getLength(), "Hello World!", null);
Upvotes: 1