In my series (Scala, JavaFX 2) - another code snippet to display a memory pie chart in a tableview with a custom renderer.
Below is the code to achieve this:
The imports in used:
import javafx.application.Application
import javafx.beans.property.SimpleLongProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.scene.control.cell.PropertyValueFactory
import javafx.scene.control.TableColumn
import javafx.scene.control.TableView
import javafx.scene.layout.BorderPane
import javafx.scene.paint.Color
import javafx.scene.Scene
import javafx.stage.Stage
import javafx.util.Callback
import javafx.scene.control.TableCell
Then the class representing one line in the table (Note the use of a tuple2 what will later be used for the chart - not really needed as the row can be accessed in the custom renderer - but other posts will follow...):
sealed class MyTableRow {
val totMem = new SimpleLongProperty(0L)
def totMemProperty = totMem
def getTotMem : Long = totMem.get
def setTotMem(value: Long) = totMem.set(value)
val maxMem = new SimpleLongProperty(0L)
def maxMemProperty = maxMem
def getMaxMem : Long = maxMem.get
def setMaxMem(value: Long) = maxMem.set(value)
val freeMem = new SimpleLongProperty(0L)
def freeMemProperty = freeMem
def getFreeMem : Long = freeMem.get
def setFreeMem(value: Long) = freeMem.set(value)
val usedMem = new SimpleLongProperty(0L)
def usedMemProperty = usedMem
def getUsedMem : Long = usedMem.get
def setUsedMem(value: Long) = usedMem.set(value)
val chartData = new SimpleObjectProperty((0L, 0L))
def chartDataProperty = chartData
def getChartData : Tuple2[Long, Long] = chartData.get
def setChartData(value: Tuple2[Long, Long]) = chartData.set(value)
}
Then the main application:
sealed class MemTable extends Application {
def runInJFXThread(f: () => Unit) = javafx.application.Platform.runLater(new Runnable() {def run() {f()}})
val timer = new java.util.Timer
val table = new TableView[MyTableRow]
val tableData = javafx.collections.FXCollections.observableArrayList[MyTableRow]()
table.setItems(tableData)
val singleRow = new MyTableRow
tableData.addAll(singleRow)
override def start(stage: Stage) = {
val borderPane = new BorderPane
val scene = new Scene(borderPane, 400, 300, Color.WHITE)
borderPane.setCenter(table)
setupUI
stage.setTitle("Memory Table")
stage.setScene(scene)
stage.show
timer.schedule(new HeapSnapshotTask, 0L, 1000L)
}
sealed class HeapSnapshotTask extends java.util.TimerTask {
val inKb = 1024L
override def run = {
val r = Runtime.getRuntime
val totalMemory = r.totalMemory / inKb
val freeMemory = r.freeMemory / inKb
val maxMemory = r.maxMemory / inKb
val usedMemory = totalMemory - freeMemory
runInJFXThread{() => {
singleRow.totMem.set(totalMemory)
singleRow.maxMem.set(maxMemory)
singleRow.freeMem.set(freeMemory)
singleRow.usedMem.set(usedMemory)
singleRow.chartData.set((freeMemory, usedMemory))
}}
println("T = " + totalMemory + ", F = " + freeMemory + ", M = " + maxMemory + ", U = " + usedMemory)
}
}
private def setupUI = {
val memColumns = new TableColumn[MyTableRow, AnyRef]("Memory")
val maxMemColumn = new TableColumn[MyTableRow, Long]("Max")
maxMemColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, Long]("maxMem"))
val totalMemColumn = new TableColumn[MyTableRow, Long]("Total")
totalMemColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, Long]("totMem"))
val freeMemColumn = new TableColumn[MyTableRow, Long]("Free")
freeMemColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, Long]("freeMem"))
val usedMemColumn = new TableColumn[MyTableRow, Long]("Used")
usedMemColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, Long]("usedMem"))
val chartColumn = new TableColumn[MyTableRow, AnyRef]("Chart")
chartColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, AnyRef]("chartData"))
val chartRenderer = new Callback[TableColumn[MyTableRow, AnyRef], TableCell[MyTableRow, AnyRef]] {
override def call(col : TableColumn[MyTableRow, AnyRef]) : TableCell[MyTableRow, AnyRef] = {
new TableCell[MyTableRow, AnyRef] {
import javafx.scene.chart.PieChart
import javafx.collections.FXCollections
import javafx.scene.layout.Pane
import javafx.scene.control.Label
val usedMemData = new PieChart.Data("Used", 0.0)
val freeMemData = new PieChart.Data("Free", 0.0)
val pieChartData = FXCollections.observableArrayList(usedMemData, freeMemData)
val pieChart = new PieChart(pieChartData)
pieChart.setPrefSize(150, 150)
pieChart.setLabelsVisible(true)
pieChart.setLegendVisible(false)
val borderPane = new BorderPane
val southPane = new Pane
setGraphic(borderPane)
borderPane.setCenter(pieChart)
borderPane.setBottom(southPane)
val southLabel = new Label
southPane.getChildren().addAll(southLabel)
override def updateItem(value : AnyRef, empty : Boolean) = {
val row = getTableRow
if (row != null && value != null) {
val datum = value.asInstanceOf[Tuple2[Long, Long]]
val free = datum._1
val used = datum._2
usedMemData.setPieValue(used)
freeMemData.setPieValue(free)
val desc = "F="+free+" U="+used
southLabel.setText(desc)
} // if
} // updateItem
}
}
} // chartRenderer
chartColumn.setCellFactory(chartRenderer)
memColumns.getColumns().addAll(maxMemColumn, totalMemColumn, freeMemColumn, usedMemColumn)
table.getColumns().addAll(memColumns, chartColumn)
}
}
object MemTable {
def main(args: Array[String]): Unit = {
javafx.application.Application.launch(classOf[MemTable])
}
}
That's it for now
1 comment:
I have this code:
c.setCellValueFactory(new PropertyValueFactory[RevCommit, _]("getFullMessage"))
I am using JGit. I get an error on that line and it says:
error: class type required but javafx.scene.control.cell.PropertyValueFactory[org.eclipse.jgit.revwalk.RevCommit, _] found
Do you happen to have ideas why your example works while this does not?
Post a Comment