Binding Chart to TableView JavaFX - javafx

I have a TableView with data, and would like a PieChart to visualize the data in that table. I can not understand how I am supposed to bind the arraylist from the TableView to the Piechart, as the TableView requires getters and setters, while the piechart requires a PieChart.Data observable list.
This is my current code, the elements are designed with Scene Builder
#FXML
private TableView<Record> tableView;
static ObservableList<Record> dataen
= FXCollections.observableArrayList(
new Record("January", 100),
new Record("February", 200));
public void initialize(URL url, ResourceBundle rb) {
Month.setCellValueFactory(new PropertyValueFactory("fieldMonth"));
Value.setCellValueFactory(new PropertyValueFactory("fieldValue"));
tableView.setItems(dataen);
}
}

Either make a listener on your TableView items list (dataen) or just use the same list for both. Here they use the same list. You could change your list to be of type <PieChart.Data> instead of <Record>, otherwise use a listener.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;
public class ChangePie extends Application {
#Override
public void start(Stage primaryStage) {
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", 13),
new PieChart.Data("Oranges", 25),
new PieChart.Data("Plums", 10),
new PieChart.Data("Pears", 22),
new PieChart.Data("Apples", 30));
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Imported Fruits");
TableView tv = new TableView(pieChartData);
tv.setEditable(true);
TableColumn tc1 = new TableColumn("Name");
tc1.setPrefWidth(100);
tc1.setCellValueFactory(new PropertyValueFactory("name"));
tc1.setCellFactory(TextFieldTableCell.forTableColumn());
TableColumn tc2 = new TableColumn("Data");
tc2.setPrefWidth(100);
tc2.setCellValueFactory(new PropertyValueFactory("pieValue"));
tc2.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
tv.getColumns().addAll(tc1,tc2);
Scene scene = new Scene(new VBox(chart,tv));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

How do I show contents from the password field in javafx using checkbox [duplicate]

This question already has answers here:
How to unmask a JavaFX PasswordField or properly mask a TextField?
(7 answers)
Closed 3 years ago.
Im a student studying java and javafx, how do I show the password in the passwordfield using a checkbox? I am using gluon scenebuilder as my fxml editor
The duplicate is listed above for the correct but more complicated way of doing this. In this answer, I am showing two examples. One with a CheckBox and the other with the all-seeing eye. The eye is to use a StackPane to layer the node. For the CheckBox solution, put a TextField and then a PasswordField in the StackPane. Bring the TextField toFront when the CheckBox is checked and set its text using the PasswordField. Clear the TextField when the CheckBox is not checked and move the PasswordField toFront. For the All-seeing eye example, use the same ideas but add an ImageView and always keep the ImageView toFront.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TestingGround extends Application
{
Image image = new Image("https://previews.123rf.com/images/andrerosi/andrerosi1905/andrerosi190500216/123158287-eye-icon-vector-look-and-vision-icon-eye-vector-icon.jpg");
#Override
public void start(Stage primaryStage)
{
HBox passwordControl1 = createPasswordFieldWithCheckBox();
HBox passwordControl2 = createPasswordFieldWithCheckBox();
StackPane passwordControl3 = createPasswordFieldWithEye();
StackPane passwordControl4 = createPasswordFieldWithEye();
VBox root = new VBox(passwordControl1, passwordControl2, passwordControl3, passwordControl4);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
HBox createPasswordFieldWithCheckBox()
{
PasswordField passwordField = new PasswordField();
passwordField.setPrefHeight(50);
TextField textField = new TextField();
textField.setPrefHeight(50);
passwordField.textProperty().bindBidirectional(textField.textProperty());
StackPane stackPane = new StackPane(textField, passwordField);
CheckBox checkBox = new CheckBox();
checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
textField.toFront();
}
else {
passwordField.toFront();
}
});
HBox root = new HBox(stackPane, checkBox);
root.setSpacing(5);
root.setAlignment(Pos.CENTER);
return root;
}
StackPane createPasswordFieldWithEye()
{
PasswordField passwordField = new PasswordField();
passwordField.setPrefHeight(50);
TextField textField = new TextField();
passwordField.textProperty().bindBidirectional(textField.textProperty());
textField.setPrefHeight(50);
ImageView imageView = new ImageView(image);
imageView.setFitHeight(32);
imageView.setFitWidth(32);
StackPane.setMargin(imageView, new Insets(0, 10, 0, 0));
StackPane.setAlignment(imageView, Pos.CENTER_RIGHT);
imageView.setOnMousePressed((event) -> {
textField.toFront();
imageView.toFront();
});
imageView.setOnMouseReleased((event) -> {
passwordField.toFront();
imageView.toFront();
});
StackPane root = new StackPane(textField, passwordField, imageView);
return root;
}
}
You could use a custom Tooltip to show the password:
import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class FxMain extends Application {
private SimpleBooleanProperty showPassword ;
private CheckBox checkBox;
private Tooltip toolTip;
private PasswordField pF;
private Stage stage;
#Override
public void start(Stage stage) {
this.stage = stage;
showPassword = new SimpleBooleanProperty();
showPassword.addListener((ChangeListener<Boolean>) (observable, oldValue, newValue) -> {
if(newValue){
showPassword();
}else{
hidePassword();
}
});
final Label message = new Label("");
Label label = new Label("Password");
toolTip = new Tooltip();
toolTip.setShowDelay(Duration.ZERO);
toolTip.setAutoHide(false);
toolTip.setMinWidth(50);
pF = new PasswordField();
pF.setOnKeyTyped(e -> {
if ( showPassword.get() ) {
showPassword();
}
});
HBox hb = new HBox(10, label, pF);
hb.setAlignment(Pos.CENTER_LEFT);
checkBox = new CheckBox("Show password");
showPassword.bind(checkBox.selectedProperty());
VBox vb = new VBox(10, hb, checkBox, message);
vb.setPadding(new Insets(10));
stage.setScene(new Scene(vb,300,100));
stage.show();
}
private void showPassword(){
Point2D p = pF.localToScene(pF.getBoundsInLocal().getMaxX(), pF.getBoundsInLocal().getMaxY());
toolTip.setText(pF.getText());
toolTip.show(pF,
p.getX() + stage.getScene().getX() + stage.getX(),
p.getY() + stage.getScene().getY() + stage.getY());
}
private void hidePassword(){
toolTip.setText("");
toolTip.hide();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFx Chart unrefresh in subscene with Oracle JDK10

I write a JavaFX Demo to add a bar chart in Subscene and change the bar chart series value in KeyFrame in Timeline.
In Oracle JDK8, the bar chart graphic refresh correct,But in Oracle JDK 10,the bar chart graphic do not refresh.
I tried Platform.requestNextPulse,but it donot useful.
Sorry for my poor English.
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.*;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class HMIBrowserDemoTest extends Application {
private Scene backScene=new Scene(new Group());
SubScene subScene =null;
private Group picGroup=null;
public HMIBrowserDemoTest(){
super();
}
private void initUI(Stage primaryStage) {
Rectangle2D screenBounds=Screen.getPrimary().getBounds();
primaryStage.setWidth(screenBounds.getWidth());
primaryStage.setHeight(screenBounds.getHeight());
primaryStage.centerOnScreen();
primaryStage.setTitle("hmi.browser.title");
primaryStage.setScene(backScene);
Group rootGroup=(Group) backScene.getRoot();
Group aa=new Group();
aa.getChildren().add(createContent1());
subScene =new SubScene(aa,800,700);
subScene.setFill(Color.BEIGE);
subScene.setManaged(false);
rootGroup.getChildren().add(subScene);
}
#Override
public void start(Stage primaryStage) throws Exception {
initUI(primaryStage);
primaryStage.show();
init1();
}
public static void main(String[] args) {
System.out.println(System.getProperty("java.library.path"));
launch(args);
}
private void init1(){
Timeline tl = new Timeline();
tl.getKeyFrames().add(
new KeyFrame(Duration.millis(150),
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
XYChart.Series series= (XYChart.Series) chart.getData().get(0);
int value= (int) (Math.random() * 5000);
XYChart.Data<String, Number> data= (XYChart.Data<String, Number>) series.getData().get(0);
System.out.println(value+"-----------");
data.setYValue(value);
subScene.toFront();
}
}
));
tl.setCycleCount(Animation.INDEFINITE);
tl.setAutoReverse(true);
tl.play();
}
private BarChart chart;
private CategoryAxis xAxis;
private NumberAxis yAxis;
public Parent createContent1() {
String[] years = {"2007", "2008", "2009"};
xAxis = new CategoryAxis();
xAxis.setCategories(FXCollections.<String>observableArrayList(years));
yAxis = new NumberAxis("Units Sold", 0.0d, 3000.0d, 1000.0d);
ObservableList<BarChart.Series> barChartData = FXCollections.observableArrayList(
new BarChart.Series("Apples", FXCollections.observableArrayList(
new BarChart.Data(years[0], 567d),
new BarChart.Data(years[1], 1292d),
new BarChart.Data(years[2], 1292d)
)),
new BarChart.Series("Lemons", FXCollections.observableArrayList(
new BarChart.Data(years[0], 956),
new BarChart.Data(years[1], 1665),
new BarChart.Data(years[2], 2559)
)),
new BarChart.Series("Oranges", FXCollections.observableArrayList(
new BarChart.Data(years[0], 1154),
new BarChart.Data(years[1], 1927),
new BarChart.Data(years[2], 2774)
))
);
chart = new BarChart(xAxis, yAxis, barChartData, 25.0d);
chart.setLayoutX(0);
chart.setLayoutY(0);
chart.setPrefSize(300,300);
return chart;
}
}

Javafx TableView in a ScrollPane

I'm having some issues with the Constrained Resize Policy for a TableView inside a ScrollPane.
It seems as though the headings do not line up completely with its column. On scroll or resize the columns snap to their correct position.
I created a small example to demonstrate:
import java.util.ArrayList;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Test extends Application
{
public static void main(String[] args) throws Exception
{
launch(args);
}
#Override
public void start(Stage primarystage) throws Exception
{
// Create layout
VBox root = new VBox();
TableView<TableObject> table = new TableView<TableObject>();
TableColumn<TableObject, String> col1 = new TableColumn<TableObject, String>("Column 1");
TableColumn<TableObject, String> col2 = new TableColumn<TableObject, String>("Column 2");
table.getColumns().addAll(col1, col2);
col1.setCellValueFactory(new PropertyValueFactory<TableObject, String>("column1"));
col2.setCellValueFactory(new PropertyValueFactory<TableObject, String>("column2"));
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
root.getChildren().add(table);
ScrollPane scrollpane = new ScrollPane();
scrollpane.setFitToWidth(true);
scrollpane.setFitToHeight(true);
scrollpane.setPrefSize(500, 200);
scrollpane.setContent(root);
// Create and show scene
Scene scene = new Scene(scrollpane);
primarystage.setScene(scene);
primarystage.show();
// Populate table
ArrayList<TableObject> data = new ArrayList<TableObject>();
for (int i = 0; i < 20;)
{
TableObject entry = new TableObject(String.valueOf(i++), String.valueOf(i++));
data.add(entry);
}
table.setItems(FXCollections.observableArrayList(data));
}
public class TableObject
{
private StringProperty column1;
private StringProperty column2;
public TableObject(String col1, String col2)
{
column1 = new SimpleStringProperty(col1);
column2 = new SimpleStringProperty(col2);
}
public StringProperty column1Property()
{
return column1;
}
public StringProperty column2Property()
{
return column2;
}
}
}
The result is this:
Is there perhaps something I am missing here?
Thanks
just show the stage after setting table items:
stage.show();
table.setItems(FXCollections.observableArrayList(data));

Data not getting displayed in Java FX Table when pressing button

I am working with Table in Java FX. The code is below :
package addsubject;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class AddSubject extends Application {
private TableView<Subject> table = new TableView<Subject>();
private final ObservableList<Subject> data
= FXCollections.observableArrayList(new Subject("Mobile Computing", "5623"));
final HBox hb = new HBox();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Add Subject");
stage.setWidth(700);
stage.setHeight(600);
final Label label = new Label("Subject Details");
label.setFont(new Font("Calibri", 20));
table.setEditable(true);
TableColumn sub = new TableColumn("Subject Name");
sub.setMinWidth(400);
sub.setCellValueFactory(
new PropertyValueFactory<Subject, String>("sub"));
sub.setCellFactory(TextFieldTableCell.forTableColumn());
sub.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Subject, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Subject, String> t) {
((Subject) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setSubName(t.getNewValue());
}
}
);
TableColumn code = new TableColumn("Subject Code");
code.setMinWidth(150);
code.setCellValueFactory(
new PropertyValueFactory<Subject, String>("code"));
code.setCellFactory(TextFieldTableCell.forTableColumn());
code.setCellFactory(TextFieldTableCell.forTableColumn());
code.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Subject, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Subject, String> t) {
((Subject) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setSubCode(t.getNewValue());
}
}
);
table.setItems(data);
table.getColumns().addAll(sub, code);
final TextField addSubName = new TextField();
addSubName.setPromptText("Subject Name");
addSubName.setPrefWidth(350);
final TextField addCode = new TextField();
addCode.setPrefWidth(150);
addCode.setPromptText("Subject Code");
final Button addButton = new Button("Add");
addButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
data.add(new Subject(
addSubName.getText(),
addCode.getText()));
addSubName.clear();
addCode.clear();
}
});
hb.getChildren().addAll(addSubName, addCode, addButton);
hb.setSpacing(5);
final VBox vbox = new VBox();
vbox.setSpacing(10);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, hb);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public static class Subject {
private final SimpleStringProperty sub;
private final SimpleStringProperty code;
private Subject(String subName, String subCode) {
this.sub = new SimpleStringProperty(subName);
this.code = new SimpleStringProperty(subCode);
}
public String getSubName() {
return sub.get();
}
public void setSubName(String subName) {
sub.set(subName);
}
public String getSubCode() {
return code.get();
}
public void setSubCode(String subCode) {
code.set(subCode);
}
}
}
I will say its working.
When I run the code, the Table should contain one row of information which is stored in 'data'. It is not displayed in the table when I run the code. How can I make it displayed ?
Next thing is to add new data to the Table when the 'Add' button is pressed after filling the 2 TextFields. I filled the 2 Text Fields, pressed the button and nothing appeared in the Table. How can I make it appear ?
The PropertyValueFactories are wrong. For example
new PropertyValueFactory<Subject, String>("sub")
This means your data object should have a method getSub() to return the value. But yours is
public String getSubName() {
return sub.get();
}
Either rename the Getter to getSub() or use new PropertyValueFactory<Subject, String>("subName")
The same applies to subject code.
You should read about JavaBeans naming conventions. Or this article on JavaFX Properties and Binding
Try implementing the following functions:
public StringProperty subProperty(){
return sub;
}
public StringProperty codeProperty(){
return code;
}
Why are these members final?

Label text position

I have a Label with an image and text
final Label label = new Label(labelText);
label.setTextAlignment(TextAlignment.CENTER);
ImageView livePerformIcon = new ImageView(MainApp.class.getResource("/images/Folder-icon.png").toExternalForm());
label.setGraphic(livePerformIcon);
I get this as a visual result:
How I can change the text position? I want to set the text below the Image?
label.setContentDisplay(ContentDisplay.TOP);
Play with this to see the effect of the different alignment settings:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
public class LabelGraphicAlignmentTest extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Label label = new Label("Some\ntext");
label.setGraphic(new ImageView(getClass().getResource("/images/Folder-icon.png").toExternalForm()));
label.setMaxWidth(Double.POSITIVE_INFINITY);
label.setMaxHeight(Double.POSITIVE_INFINITY);
label.setStyle("-fx-border-color: blue;");
root.setCenter(label);
ComboBox<ContentDisplay> contentDisplayBox = new ComboBox<>();
contentDisplayBox.getItems().addAll(ContentDisplay.values());
contentDisplayBox.getSelectionModel().select(ContentDisplay.LEFT);
label.contentDisplayProperty().bind(contentDisplayBox.valueProperty());
ComboBox<Pos> alignmentBox = new ComboBox<>();
alignmentBox.getItems().addAll(Pos.values());
alignmentBox.getSelectionModel().select(Pos.CENTER);
label.alignmentProperty().bind(alignmentBox.valueProperty());
ComboBox<TextAlignment> textAlignmentBox = new ComboBox<>();
textAlignmentBox.getItems().addAll(TextAlignment.values());
textAlignmentBox.getSelectionModel().select(TextAlignment.LEFT);
label.textAlignmentProperty().bind(textAlignmentBox.valueProperty());
GridPane ctrls = new GridPane();
ctrls.setHgap(5);
ctrls.setVgap(5);
ctrls.setPadding(new Insets(10));
ctrls.addRow(0, new Label("Content display:"), new Label("Alignment:"), new Label("Text Alignment:"));
ctrls.addRow(1, contentDisplayBox, alignmentBox, textAlignmentBox);
root.setTop(ctrls);
Scene scene = new Scene(root, 600, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I had to center the text of a label which acted like a title. The following code snippet did the trick.
final Label title = new Label("Some text");
title.setMaxWidth(Double.MAX_VALUE);
title.setAlignment(Pos.CENTER);
Good programming :-)
I was able to grab the button from the fxml file:
#FXML Label countDownClockLabel;
Then when the controller was initialized i set the text position:
#FXML
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
countDownClockLabel.setAlignment(Pos.CENTER);
}
You have to import:
import javafx.geometry.Pos;

Resources