我正在尝试按需向我的Swing应用程序的用户显示日志内容。显示日志事件列表,可能允许他们查看有关日志消息的详细信息,理想情况下与日食“错误日志”视图显示的内容类似。
是否有任何预制的日志显示组件/日志追加器?
我意识到我可以轻松地将字符串值附加到Textarea但是如果可能的话我会更喜欢“免费”(搜索,按事件过滤,按记录器过滤,导出等)
我目前正在使用SLF4J进行回溯,但是如果存在这样的组件,我在切换到另一个日志框架时没有任何问题。
答案 0 :(得分:1)
这是一个更大的工作应用程序的一部分,所以虽然我只是
发布与此问题相关的代码,有一些工件
应用程序。代码在Scala中,但降级到Java应该
直截了当。我不包括大多数import
指令;
希望很清楚我指的是哪些课程。一世
相信只有两个具有冲突的简单类名的类是
scala.swing.Component
和java.awt.Component。
代码存在于以下文件中:
Main.scala
具有创建日志窗口的代码。LogFrame
是显示日志条目的swing窗口LogModel
存储日志记录数据AbstractBaseTableModel
是LogModel
的超类以及
我的应用程序中的另一个类未在此处显示。TableAppender.scala
是将Swing连接到Logback的内容。logback.xml
有一行激活我的新appender 在Main.scala
中,显示日志输出的Frame
可见:
object Main extends swing.SwingApplication {
override def startup(args: Array[String]) {
val logFrame = LogFrame
if (logFrame.size == new Dimension(0,0)) logFrame.pack()
logFrame.visible = true
}
}
LogFrame
单例对象在LogFrame.scala
:
object LogFrame extends Frame {
title = "Log"
iconImage = new ImageIcon("log.png").getImage
preferredSize = new Dimension(1200,370)
object LogTable extends Table {
model = LogModel
Map(0 -> 50, 1 -> 32, 4 -> 400) foreach { m =>
peer.getColumnModel getColumn m._1 setPreferredWidth m._2
}
override def rendererComponent(
isSelected: Boolean, focused: Boolean, row: Int, column: Int
) = {
val v = model.getValueAt(
peer.convertRowIndexToModel(row),
peer.convertColumnIndexToModel(column)
).toString
TableCellRenderer.componentFor(this, isSelected, focused, v, row, column)
}
import ch.qos.logback.classic.Level.{ERROR,WARN}
object TableCellRenderer extends AbstractRenderer[String, TextArea](new TextArea {
lineWrap = true; wordWrap = true
}) {
val brown = new java.awt.Color(143,112,0)
def configure(t: Table, sel: Boolean, foc: Boolean, s: String, row: Int, col: Int) = {
component.text = s
model.getValueAt(
LogTable.this.peer.convertRowIndexToModel(row),
LogModel.columnNames.indexOf("Level")
) match {
case ERROR => component.foreground = java.awt.Color.RED
case WARN => component.foreground = brown
case _ =>
}
}
}
}
contents = new BoxPanel(Vertical) {
contents += new ScrollPane { viewportView = LogTable }
}
def logEvent(event: ILoggingEvent) {
event +=: LogModel
}
}
LogModel
单身人士在LogModel.scala
。
object LogModel extends AbstractBaseTableModel {
final val columnNames = Array("Time","Level","Thread","Logger","Message")
val data = ListBuffer[Array[AnyRef]]()
def +=:(event: ILoggingEvent) {
Array[AnyRef](
formatTimeStamp(event.getTimeStamp),
event.getLevel,
event.getThreadName,
event.getLoggerName.replaceFirst(".*\\.",""),
event.getFormattedMessage
) +=: data
fireTableChanged( new TableModelEvent(this) )
}
}
我的包对象中的这两行定义了
formatTimeStamp()
方法:
final val isoFormatter = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis
def formatTimeStamp(millis: Long) = isoFormatter.print(millis)
LogModel
延伸AbstractBaseTableModel
的原因是因为我
应用程序有一些其他表格模型,一次更新,
而不是像日志记录模型那样的一行。从而
AbstractBaseTableModel
的{{1}}成员类型为data
子类可以使用不可变的SeqLike
或可变的
根据需要List
。
ListBuffer
import scala.collection.SeqLike
abstract class AbstractBaseTableModel extends AbstractTableModel {
val columnNames: Array[String]
val data: SeqLike[Array[AnyRef],_]
def getRowCount: Int = data.size
def getColumnCount: Int = columnNames.size
override def getColumnName(column: Int) = columnNames(column)
override def getValueAt(row: Int, column: Int): AnyRef = data(row)(column)
override def isCellEditable(row: Int, col: Int) = false
override def getColumnClass(columnIndex: Int): Class[_] =
getValueAt(0, columnIndex).getClass
}
文件很小:
TableAppender.scala
最后,对class TableAppender extends AppenderBase[ILoggingEvent] {
def append(event: ILoggingEvent) {
LogFrame.logEvent(event)
}
}
文件的更改甚至更小:
logback.xml
唯一阻止我决定这个问题的问题 比老式的日志文件更好:
1)因为我已经覆盖了<appender name="swingTable" class="mypackage.TableAppender"/>
,
Table.rendererComponent()
无法正常工作。
2)我还没弄明白如何让包裹的线条可见 桌子。我所知道的是,我必须增加高度 行。
如果这些问题得到解决,接下来就要补充一下 根据日志级别和记录器名称进行实时过滤。就这样 是的,我现在至少要把它放在一边,但如果有的话 有什么建议,我有兴趣听听他们。
以下资源对我构成前述内容有用 代码,或者在解决剩余问题时可能有用:
Idiomatic use of Scala table cell renderers,
一个非常有用的答案
oxbow_lakes,但是
遗憾的是,我们未解决JTable.setDefaultRenderer()
问题。
Table Row Rendering, Rob Camick的博客文章, 解释了如何更改表格行的颜色。
答案 1 :(得分:0)
我会看SwingX。它在这个页面有一个很好的演示。以JXTable为例。