Last article demonstrate how to implement "Editable multi-column TableView". It's modified to work with StackedBarChart, all the data series in StackedBarChart can be changed with the TableView.
Instead of share a common ObservableList<XYChart.Data>, a class MyList is implemented. It hold a ObservableList<Record> for TableView, and two ObservableList<XYChart.Data> for StackedBarChart, and also keep their content consistency.
Once editing of the table committed, the handler update the ObservableList<Record> for TableView, and also the corresponding ObservableList<XYChart.Data> for StackedBarChart.
package javafxmulticolumnchart;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @web http://java-buddy.blogspot.com/
*/
public class JavaFXMultiColumnChart extends Application {
public class Record{
private SimpleStringProperty fieldMonth;
private SimpleDoubleProperty fieldValue1;
private SimpleDoubleProperty fieldValue2;
Record(String fMonth, double fValue1, double fValue2){
this.fieldMonth = new SimpleStringProperty(fMonth);
this.fieldValue1 = new SimpleDoubleProperty(fValue1);
this.fieldValue2 = new SimpleDoubleProperty(fValue2);
}
public String getFieldMonth() {
return fieldMonth.get();
}
public double getFieldValue1() {
return fieldValue1.get();
}
public double getFieldValue2() {
return fieldValue2.get();
}
public void setFieldMonth(String fMonth) {
fieldMonth.set(fMonth);
}
public void setFieldValue1(Double fValue1) {
fieldValue1.set(fValue1);
}
public void setFieldValue2(Double fValue2) {
fieldValue2.set(fValue2);
}
}
class MyList {
ObservableList<Record> dataList;
ObservableList<XYChart.Data> xyList1;
ObservableList<XYChart.Data> xyList2;
MyList(){
dataList = FXCollections.observableArrayList();
xyList1 = FXCollections.observableArrayList();
xyList2 = FXCollections.observableArrayList();
}
public void add(Record r){
dataList.add(r);
xyList1.add(new XYChart.Data(r.getFieldMonth(), r.getFieldValue1()));
xyList2.add(new XYChart.Data(r.getFieldMonth(), r.getFieldValue2()));
}
public void update1(int pos, Double val){
xyList1.set(pos, new XYChart.Data(xyList1.get(pos).getXValue(), val));
}
public void update2(int pos, Double val){
xyList2.set(pos, new XYChart.Data(xyList2.get(pos).getXValue(), val));
}
}
MyList myList;
private TableView<Record> tableView = new TableView<>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("java-buddy.blogspot.com");
//prepare myList
myList = new MyList();
myList.add(new Record("January", 100, 120));
myList.add(new Record("February", 200, 210));
myList.add(new Record("March", 50, 70));
myList.add(new Record("April", 75, 50));
myList.add(new Record("May", 110, 120));
myList.add(new Record("June", 300, 200));
myList.add(new Record("July", 111, 100));
myList.add(new Record("August", 30, 50));
myList.add(new Record("September", 75, 70));
myList.add(new Record("October", 55, 50));
myList.add(new Record("November", 225, 225));
myList.add(new Record("December", 99, 100));
Group root = new Group();
tableView.setEditable(true);
Callback<TableColumn, TableCell> cellFactory =
new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn p) {
return new EditingCell();
}
};
TableColumn columnMonth = new TableColumn("Month");
columnMonth.setCellValueFactory(
new PropertyValueFactory<Record,String>("fieldMonth"));
columnMonth.setMinWidth(60);
TableColumn columnValue1 = new TableColumn("Value 1");
columnValue1.setCellValueFactory(
new PropertyValueFactory<Record,Double>("fieldValue1"));
columnValue1.setMinWidth(60);
TableColumn columnValue2 = new TableColumn("Value 2");
columnValue2.setCellValueFactory(
new PropertyValueFactory<Record,Double>("fieldValue2"));
columnValue2.setMinWidth(60);
//--- Add for Editable Cell of Value field, in Double
columnValue1.setCellFactory(cellFactory);
columnValue1.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Record, Double>>() {
@Override public void handle(TableColumn.CellEditEvent<Record, Double> t) {
((Record)t.getTableView().getItems().get(
t.getTablePosition().getRow())).setFieldValue1(t.getNewValue());
int pos = t.getTablePosition().getRow();
myList.update1(pos, t.getNewValue());
}
});
columnValue2.setCellFactory(cellFactory);
columnValue2.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Record, Double>>() {
@Override public void handle(TableColumn.CellEditEvent<Record, Double> t) {
((Record)t.getTableView()
.getItems()
.get(t.getTablePosition().getRow())).setFieldValue2(t.getNewValue());
int pos = t.getTablePosition().getRow();
myList.update2(pos, t.getNewValue());
}
});
//--- Prepare StackedBarChart
List<String> monthLabels = Arrays.asList(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");
final CategoryAxis xAxis1 = new CategoryAxis();
final NumberAxis yAxis1 = new NumberAxis();
xAxis1.setLabel("Month");
xAxis1.setCategories(FXCollections.<String> observableArrayList(monthLabels));
yAxis1.setLabel("Value 1");
XYChart.Series XYSeries1 = new XYChart.Series(myList.xyList1);
XYSeries1.setName("XYChart.Series 1");
final CategoryAxis xAxis2 = new CategoryAxis();
final NumberAxis yAxis2 = new NumberAxis();
xAxis2.setLabel("Month");
xAxis2.setCategories(FXCollections.<String> observableArrayList(monthLabels));
yAxis2.setLabel("Value 2");
XYChart.Series XYSeries2 = new XYChart.Series(myList.xyList2);
XYSeries2.setName("XYChart.Series 2");
final StackedBarChart<String,Number> stackedBarChart = new StackedBarChart<>(xAxis1,yAxis1);
stackedBarChart.setTitle("StackedBarChart");
stackedBarChart.getData().addAll(XYSeries1, XYSeries2);
//---
tableView.setItems(myList.dataList);
tableView.getColumns().addAll(columnMonth, columnValue1, columnValue2);
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.getChildren().addAll(tableView, stackedBarChart);
root.getChildren().add(hBox);
primaryStage.setScene(new Scene(root, 750, 400));
primaryStage.show();
}
class EditingCell extends TableCell<Record, Double> {
private TextField textField;
public EditingCell() {}
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.selectAll();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(String.valueOf(getItem()));
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()*2);
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(Double.parseDouble(textField.getText()));
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
}
Another example to make PieChart and LineChart update dynamically with TableView.
No comments:
Post a Comment