2011-12-17 61 views
2

我正在嘗試使Log4J登錄到JTextPane。我想使用TextPane,因爲我想要基本突出顯示(例如,錯誤是紅色的,信息是綠色的)。JTextPane中的log4j

我有兩個記錄器設置,一個(根記錄器)將所有記錄到一個文件中,另一個(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() - 方法從上JTextPane
  • 一個 SwingWorker
  • 方法,如validate()revalidate()repaint()執行insertString() - 方法
  • 不使用全球StyledDocument - 對象,但直接從log -instance:log.getStyledDocument().insertString(0, "Hello World!", info_log);
  • setText()-JTextPane的方法(僅適用於構造函數)。

由於JTextPane沒有fireContentChanged() - 方法(或類似),我有點失去了在這裏。


我身邊多一點玩,發現了一些其他的東西:

  • StyledDocument被更新(調用getText()表明文本已插入)。
  • 當我直接從編譯器調用append()insertString()-方法(在初始化StyledDocumentJTextPane後),它一切正常。

另外,我檢查哪個線程調用該方法通過將此到append() - 方法體:

System.out.println("Thread: "+Thread.currentThread().getName()); 

它表明,如果我只是做兩個日誌語句從代碼某處以下內容:

Thread: AWT-EventQueue-0 
Thread: AWT-EventQueue-0 

,當我調用append() -method直接從Log -class(加上從上述兩個測井語句)的構造,它示出了以下內容:

Thread: AWT-EventQueue-0 
Thread: AWT-EventQueue-0 
Thread: AWT-EventQueue-0 

第一次調用可能附加文本。但另外兩個人不縫合工作。

我的GUI是通過使用SwingUtilities.invokeLater()AWT-EventQueue建立的。這兩個日誌記錄調用是在相同的上下文中進行的(因此也來自EventQueue)。

+0

你確定你不是複製'org.apache.log4j.lf5.LF5Appender'? – 2011-12-17 18:58:44

+0

@ʘleg這個看起來有點「超載」爲我的目的。 – 2011-12-17 19:45:43

回答

2

文本窗格對appender是私有的,並且您沒有任何getter。所以我猜想GUI有一個文本窗格,並且記錄器有另外一個文本窗格它附加到。

這樣,或者您從Log實例獲取文本窗格,該實例與Log4j實例化的Log實例不同。

此外,appender可能會被多個線程使用,但Swing組件只能從事件派發線程訪問。文本窗格的每個附加內容都應在SwingUtilities.invokeLater()調用中完成。

+0

Log類有一個getView()方法,它返回私有的JTextPane。我將它添加到代碼剪切。由於我沒有附加到TextPane本身,而是附加到「StyledDocument」,我沒有修改它,或者我在這裏錯了嗎? – 2011-12-17 19:37:08

+0

我向我的問題添加了更多信息,請看看。 – 2011-12-18 13:05:06

+0

你是如何從appender獲得文本窗格的?告訴我們用來做這件事的代碼。我的猜測是你Log4J和你的代碼不使用相同的Log實例。 – 2011-12-18 13:19:27

1

檢查是否不要;不要調用setText()或setContentType(),可能是一些重新創建Document的方法。而不是保存對文檔的引用從窗格中獲取它。 不

doc.insertString(doc.getLength(), "Hello World!", null); 

log.getStyledDocument().insertString(doc.getLength(), "Hello World!", null); 
+0

我不會調用上述任何方法。直接獲取參考也無效。我在我的問題中添加了更多信息,請看看。 – 2011-12-18 13:02:55

+0

+1由於Log4J允許將輸出保存到控制檯,文件或數據庫中,因此我在'Runnble#Thread'內發送了simlair(已刪除)答案,但是我得到了'你在這裏顯示的是什麼?','@Lukas Knuth'他錯過了'Log4J'和'Swing JComponents'之間的API橋 – mKorbel 2011-12-18 13:52:02