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.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
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 fieldDay;
private SimpleDoubleProperty fieldValue1;
private SimpleDoubleProperty fieldValue2;
Record(String fDay, double fValue1, double fValue2){
this.fieldDay = new SimpleStringProperty(fDay);
this.fieldValue1 = new SimpleDoubleProperty(fValue1);
this.fieldValue2 = new SimpleDoubleProperty(fValue2);
}
public String getFieldDay() {
return fieldDay.get();
}
public double getFieldValue1() {
return fieldValue1.get();
}
public double getFieldValue2() {
return fieldValue2.get();
}
public void setFieldDay(String fDay) {
fieldDay.set(fDay);
}
public void setFieldValue1(Double fValue1) {
fieldValue1.set(fValue1);
}
public void setFieldValue2(Double fValue2) {
fieldValue2.set(fValue2);
}
}
class MyList {
ObservableList<Record> dataList;
ObservableList<PieChart.Data> pieChartData1;
ObservableList<XYChart.Data> xyList2;
MyList(){
dataList = FXCollections.observableArrayList();
pieChartData1 = FXCollections.observableArrayList();
xyList2 = FXCollections.observableArrayList();
}
public void add(Record r){
dataList.add(r);
pieChartData1.add(new PieChart.Data(r.getFieldDay(), r.getFieldValue1()));
xyList2.add(new XYChart.Data(r.getFieldDay(), r.getFieldValue2()));
}
public void update1(int pos, Double val){
pieChartData1.set(pos, new PieChart.Data(pieChartData1.get(pos).getName(), 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("Sunday", 100, 120));
myList.add(new Record("Monday", 200, 210));
myList.add(new Record("Tuesday", 50, 70));
myList.add(new Record("Wednesday", 75, 50));
myList.add(new Record("Thursday", 110, 120));
myList.add(new Record("Friday", 300, 200));
myList.add(new Record("Saturday", 111, 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 columnDay = new TableColumn("Day");
columnDay.setCellValueFactory(
new PropertyValueFactory<Record,String>("fieldDay"));
columnDay.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> dayLabels = Arrays.asList(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday");
final PieChart pieChart1 = new PieChart(myList.pieChartData1);
pieChart1.setPrefWidth(200);
pieChart1.setTitle("Pie Chart 1");
final CategoryAxis xAxis2 = new CategoryAxis();
final NumberAxis yAxis2 = new NumberAxis();
xAxis2.setLabel("Day");
xAxis2.setCategories(FXCollections.<String> observableArrayList(dayLabels));
yAxis2.setLabel("Value 2");
XYChart.Series XYSeries2 = new XYChart.Series(myList.xyList2);
XYSeries2.setName("XYChart.Series 2");
final LineChart<String,Number> lineChart2 =
new LineChart<>(xAxis2,yAxis2);
lineChart2.setTitle("Line Chart 2");
lineChart2.setPrefWidth(250);
lineChart2.getData().add(XYSeries2);
//---
tableView.setItems(myList.dataList);
tableView.getColumns().addAll(columnDay, columnValue1, columnValue2);
tableView.setPrefWidth(200);
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.getChildren().addAll(tableView, pieChart1, lineChart2);
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();
}
}
}
Saturday, March 2, 2013
JavaFX: Interaction between table and charts
Last article demonstrate "Update StackedBarChart dynamically, with TableView". It's another example to make PieChart and LineChart update dynamically with TableView.
JavaFX 2: Update StackedBarChart dynamically, with TableView.
In the former article "Create dynamic StackedBarChart of JavaFX 2" demonstrate how to update StackedBarChart dynamically, with TableView. BUT it's not a good example! Both the TableView and one data series of the StackedBarChart work with the same ObservableList<XYChart.Data>, only one data series of the StackedBarChart can be modified with the TableView. And hard to extend to update more data series.
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.
Another example to make PieChart and LineChart update dynamically with TableView.
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.
JavaFX: Editable multi-column TableView
Example of Editable multi-column TableView of JavaFX.
Related:
- JavaFX: Editable TableView with dynamic row
package javafxmulticolumnchart;
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.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.VBox;
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);
}
}
private TableView<Record> tableView = new TableView<>();
private ObservableList<Record> dataList =
FXCollections.observableArrayList(
new Record("January", 100, 120),
new Record("February", 200, 210),
new Record("March", 50, 70),
new Record("April", 75, 50),
new Record("May", 110, 120),
new Record("June", 300, 200),
new Record("July", 111, 100),
new Record("August", 30, 50),
new Record("September", 75, 70),
new Record("October", 55, 50),
new Record("November", 225, 225),
new Record("December", 99, 100));
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("java-buddy.blogspot.com");
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());
}
});
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());
}
});
//---
tableView.setItems(dataList);
tableView.getColumns().addAll(columnMonth, columnValue1, columnValue2);
VBox vBox = new VBox();
vBox.setSpacing(10);
vBox.getChildren().add(tableView);
root.getChildren().add(vBox);
primaryStage.setScene(new Scene(root, 300, 350));
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();
}
}
}
Related:
- JavaFX: Editable TableView with dynamic row
Subscribe to:
Posts (Atom)
