我目前正在尝试使 Log4J 登录到 JTextPane
。我想使用 TextPane,因为我想要基本的突出显示(例如,错误为红色,信息为绿色)。
我设置了两个记录器,一个(根记录器)将所有内容记录到文件中,另一个(guiLogger
)仅在 JTextPane 中记录 GUI 上的一些错误和信息
.
我当前面临的问题是,我无法附加到 TextPane 来工作。我目前拥有的看起来像这样:
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;
}
}
Log4J 配置文件如下所示:
# 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
调用 append()
方法,并且 insertString()
方法执行清理(它不会进入 catch
)- block ),但我在 GUI 上的 TextPane 中没有看到任何内容。
我尝试解决这个问题:
- 使用
SwingUtilities.invokeLater()
执行insertString()
方法 - 从
SwingWorker
执行insertString()
方法 JTextPane
上的validate()
、revalidate()
和repaint()
等方法- 不使用全局
StyledDocument
对象,而是直接从log
实例获取它:log.getStyledDocument().insertString(0, "Hello World !", info_log);
JTextPane
的setText()
方法(仅在构造函数中有效)。
由于JTextPane
没有fireContentChanged()
方法(或类似的),我有点迷失在这里。
我玩了更多,发现了一些其他东西:
StyledDocument
已更新(调用getText()
显示文本已插入)。- 当我直接从编译器调用
append()
或insertString()
方法时(在初始化StyledDocument
和>JTextPane
),一切正常。
此外,我通过将其添加到 append()
方法主体来检查哪个线程调用了该方法:
System.out.println("Thread: "+Thread.currentThread().getName());
如果我只是从代码中的某个位置执行两个日志语句,它会显示以下内容:
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
当我直接从 Log
类的构造函数调用 append()
方法(加上上面的两个日志记录语句)时,它显示以下:
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
Thread: AWT-EventQueue-0
第一次调用可能会附加文本。但另外两个似乎不起作用。
我的 GUI 是使用 SwingUtilities.invokeLater()
从 AWT-EventQueue
构建的。这两个日志记录调用是在同一上下文中进行的(因此也来自 EventQueue)。
最佳答案
文本 Pane 对于附加程序来说是私有(private)的,并且您没有任何 setter/getter 。所以我猜测 GUI 有一个文本 Pane ,并且记录器有另一个附加的文本 Pane 。
或者您从与 Log4j 实例化的 Log 实例不同的 Log 实例获取文本 Pane 。
此外,appender 可能由多个线程使用,但 Swing 组件只能从事件分派(dispatch)线程访问。文本 Pane 的每次追加都应在 SwingUtilities.invokeLater()
调用内完成。
关于java - JTextPane 中的 log4j,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8546995/