JavaFX TreeTableView and ContextMenu - javafx

In my project I have a TreeTableView with 5 columns.
I need a different context Menu for every columns.
I have created a ContextMenu in Source Builder for every columns (in the example you see only one for "value" column), but the menĂ¹ appears only with right click on column header, but I need the menĂ¹ appears only on right click on cell value
<TreeTableView fx:id="valueTable" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<columns>
<TreeTableColumn fx:id="context" prefWidth="483.20001524686813" sortable="false" text="Context" />
<TreeTableColumn fx:id="tag" minWidth="50.0" prefWidth="90.0" sortable="false" text="Tag" />
<TreeTableColumn fx:id="offset" minWidth="50.0" prefWidth="90.0" sortable="false" text="OffSet" />
<TreeTableColumn fx:id="lenght" minWidth="50.0" prefWidth="90.0" sortable="false" text="Lenght" />
<TreeTableColumn fx:id="value" prefWidth="367.99993896484375" sortable="false" text="Value">
<contextMenu>
<ContextMenu fx:id="contextMenuValue" >
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
<MenuItem mnemonicParsing="false" text="Action 3" />
<MenuItem mnemonicParsing="false" text="Action 4" />
</items>
</ContextMenu>
</contextMenu>
</TreeTableColumn>
</columns>
</TreeTableView>
I try to add this code for check the MouseClick event, but event is intercepted only on TreeTableView "valueTable" and not on TreeTableColumn "value".
value.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
System.out.println("Work Cell");
});
valueTable.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
System.out.println("Work Table");
});
Can you help me?
Regard.

You can do it by implementing a custom TreeTableCell then add the ContextMenu to the cell instead of the column like:
public class Controller implements Initializable {
#FXML
private TreeTableView<MyModel> table;
#FXML
private TreeTableColumn<MyModel, String> first;
#FXML
private TreeTableColumn<MyModel, Boolean> second;
#Override
public void initialize(URL location, ResourceBundle resources) {
first.setCellValueFactory(data -> data.getValue().getValue().nameProperty());
first.setCellFactory(cell -> new MyCell());
second.setCellValueFactory(data -> data.getValue().getValue().selectedProperty());
MyModel john = new MyModel("John");
MyModel andrew = new MyModel("Andrew");
table.setRoot(new TreeItem<>());
table.setShowRoot(false);
table.getRoot().getChildren().add(new TreeItem<>(john));
table.getRoot().getChildren().add(new TreeItem<>(andrew));
}
private class MyModel {
private StringProperty name;
private BooleanProperty selected;
MyModel(String name) {
this.name = new SimpleStringProperty(name);
this.selected = new SimpleBooleanProperty(false);
}
StringProperty nameProperty() {
return name;
}
BooleanProperty selectedProperty() {
return selected;
}
}
private class MyMenu extends ContextMenu {
MyMenu() {
getItems().add(new MenuItem("Test"));
getItems().add(new MenuItem("Item"));
}
}
private class MyCell extends TreeTableCell<MyModel, String> {
MyCell() {
// Here you can set the same menu for each cell. Then the column is having the same cell for every row
setContextMenu(new MyMenu());
}
// Overridden just to show the text of the cell.
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
contextMenuProperty().bind(Bindings
// here you can define your own condition
.when(getTreeTableRow().getTreeItem().getValue().selectedProperty())
.then(new MyMenu())
.otherwise((MyMenu) null));
setText(item);
}
}
}
}
Of course you can set a different menu for the second column same as it is set for the first one.

I have resolved with
value.setCellFactory(tc -> {
TreeTableCell<MyModel, String> cell = new TreeTableCell<MyModel, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty) ;
setText(empty ? null : item);
}
};
cell.setOnMouseClicked(e -> {
if (! cell.isEmpty()) {
String userId = cell.getItem();
System.out.println("Work!");
}
});
return cell ;
});

Related

Can't read text from TextField input from DialogPane, JavaFX

I am trying to create a simple Contacts Application in JavaFX. It has a main window with TableView and a DialogPane opening when I want to create new contact. In the DialogPane there are several TextFields from which I want to collect text in order to create a Contacts List. My problem is that when I want to read the input from the DialogPane (from TextFields), which is the separate fxml file with separate controller (separate from main Controller) the application runs an error (java.lang.NullPointerException). And when I put a TextField in my main window FXML file, then I can access this text from the textField just fine. Why do I get an error when I want to read data from DialogPane (Error-->File: Controller.java, I commented the section where I get an error)?? I am stuck. Can anyone suggest what am I doing wrong? Here is my code:
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("mainwindow.fxml"));
primaryStage.setTitle("Your Contacts");
primaryStage.setScene(new Scene(root, 900, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java
public class Controller {
#FXML
private BorderPane mainPanel;
public ObservableList<Contact> contactsList = FXCollections.observableArrayList();
#FXML
public void showAddContactDialog() {
Dialog<ButtonType> dialog = new Dialog<>();
dialog.initOwner(mainPanel.getScene().getWindow());
dialog.setTitle("Add new contact");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("addContactDialog.fxml"));
try {
dialog.getDialogPane().setContent(fxmlLoader.load());
} catch (IOException e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("Couldn't load the dialog");
alert.showAndWait();
e.printStackTrace();
return;
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
if(result.isPresent() && result.get() == ButtonType.OK) {
//========================================================================================
//here is the error, I cannot read values from addContactDialog controller
ContactController contactController = new ContactController();
String firstName = contactController.getNewContact().getFirstName();
String lastName = contactController.getNewContact().getLastName();
String phoneNumber = contactController.getNewContact().getPhoneNumber();
String emailAddress = contactController.getNewContact().getEmailAddress();
Contact newContact = new Contact(firstName, lastName, phoneNumber, emailAddress);
contactsList.add(newContact);
//or alternatively
// Contact newContact = contactController.getNewContact();
// contactsList.add(newContact);
//========================================================================================
}
}
}
ContactController.java
public class ContactController {
#FXML
private TextField firstNameField;
#FXML
private TextField lastNameField;
#FXML
private TextField phoneNumberFiled;
#FXML
private TextField emailField;
public Contact getNewContact() {
String firstName = firstNameField.getText();
String lastName = lastNameField.getText();
String phoneNumber = phoneNumberFiled.getText();
String emailAddress = emailField.getText();
Contact newContact = new Contact(firstName, lastName, phoneNumber, emailAddress);
return newContact;
}
Contact.java
public class Contact {
private SimpleStringProperty firstName = new SimpleStringProperty("");
private SimpleStringProperty lastName = new SimpleStringProperty("");
private SimpleStringProperty phoneNumber = new SimpleStringProperty("");
private SimpleStringProperty emailAddress = new SimpleStringProperty("");
public Contact() {
}
public Contact(String firstName, String lastName, String phoneNumber, String emailAddress) {
this.firstName.set(firstName);
this.lastName.set(lastName);
this.phoneNumber.set(phoneNumber);
this.emailAddress.set(emailAddress);
}
public String getFirstName() {
return firstName.get();
}
public SimpleStringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public SimpleStringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getPhoneNumber() {
return phoneNumber.get();
}
public SimpleStringProperty phoneNumberProperty() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber.set(phoneNumber);
}
public String getEmailAddress() {
return emailAddress.get();
}
public SimpleStringProperty emailAddressProperty() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress.set(emailAddress);
}
#Override
public String toString() {
return "Contact{" +
"firstName=" + firstName +
", lastName=" + lastName +
", phoneNumber=" + phoneNumber +
", emailAddress=" + emailAddress +
'}';
}
}
mainwindow.fxml
<BorderPane fx:id="mainPanel" fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml">
<top>
<MenuBar>
<menus>
<Menu text="Contacts">
<items>
<MenuItem text="Add new" onAction="#showAddContactDialog"/>
</items>
<items>
<MenuItem text="Edit" />
</items>
<items>
<MenuItem text="Delete"/>
</items>
<items>
<MenuItem text="Exit"/>
</items>
</Menu>
</menus>
<menus>
<Menu text="Info">
<items>
<MenuItem text="About"/>
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<TableView fx:id="contactsTable">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
<columns>
<TableColumn text="First Name">
<cellValueFactory>
<PropertyValueFactory property="firstName"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Last Name">
<cellValueFactory>
<PropertyValueFactory property="lastName"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Phone Number">
<cellValueFactory>
<PropertyValueFactory property="phoneNumber"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Email">
<cellValueFactory>
<PropertyValueFactory property="emailAddress"/>
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</center>
</BorderPane>
addContactDialog.fxml
<DialogPane fx:controller="sample.ContactController" xmlns:fx="http://javafx.com/fxml">
<headerText>
Fill in the information for the new Contact
</headerText>
<content>
<GridPane vgap="10" hgap="10">
<Label text="First Name: " GridPane.rowIndex="0" GridPane.columnIndex="0"/>
<TextField fx:id="firstNameField" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
<Label text="Last Name: " GridPane.rowIndex="1" GridPane.columnIndex="0"/>
<TextField fx:id="lastNameField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Phone Number: " GridPane.rowIndex="2" GridPane.columnIndex="0"/>
<TextField fx:id="phoneNumberField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<Label text="Notes: " GridPane.rowIndex="3" GridPane.columnIndex="0"/>
<TextField fx:id="notesField" GridPane.rowIndex="3" GridPane.columnIndex="1"/>
</GridPane>
</content>
</DialogPane>
Ok, I found the mistake - I made a typo in the ContactController.java file. It should have phoneNumberField instead of phoneNumberFiled String...
Did you tried putting .toString
like this
String firstName = contactController.getNewContact().getFirstName().toString();

javaFX: TableView's cellvalue is not enough to display in columns i can't solved [duplicate]

This question already has answers here:
Javafx tableview not showing data in all columns
(3 answers)
Closed 5 years ago.
javaFX: TableView's cellvalue is not enough to display in columns i can't solved, The following code executes, but the column is showing anything.
and display is like picture pict
this is Ligne_Commande class :
package pfe;
public class Ligne_Commande {
private int n_liv1;
private String des_art1;
private float prix_vent1;
private int qte_com1;
public Ligne_Commande(){
super();
}
public Ligne_Commande(String des_art, int qte_com, float prix_vent){
super();
this.des_art1= des_art;
this.prix_vent1= prix_vent;
this.qte_com1= qte_com;
}
public void setN_liv1(int n_liv) {
this.n_liv1 = n_liv;
}
public void setN_art1(String des_art) {
this.des_art1 = des_art;
}
public void setPrix_vent1(float prix_vent) {
this.prix_vent1 = prix_vent;
}
public void setQte_com1(int qte_com) {
this.qte_com1 = qte_com;
}
public int getN_liv1() {
return n_liv1;
}
public String getN_art1() {
return des_art1;
}
public float getPrix_vent1() {
return prix_vent1;
}
public int getQte_com1() {
return qte_com1;
}
}
and FXML controller :
#FXML
private TableView<Ligne_Commande> tableview_art_qte;
#FXML
private TableColumn<Ligne_Commande, String> col_art_commande;
#FXML
private TableColumn<Ligne_Commande, Integer> col_qte_commande;
#FXML
private TableColumn<Ligne_Commande, Float> col_prix_vent;
#Override
public void initialize(URL url, ResourceBundle rb) {
ObservableList<Ligne_Commande> data = FXCollections.observableArrayList();
data.add(new Ligne_Commande("pommme", 100, 125));
col_art_commande.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, String>("des_art1"));
col_qte_commande.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, Integer>("qte_com1"));
col_prix_vent.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, Float>("prix_vent1"));
tableview_art_qte.setItems(data);
}
FXML file :
<TableView fx:id="tableview_art_qte" editable="true" prefHeight="381.0" prefWidth="230.0" GridPane.columnIndex="2" GridPane.rowIndex="3">
<columns>
<TableColumn fx:id="col_art_commande" prefWidth="75.0" text="Article Commande" />
<TableColumn fx:id="col_qte_commande" maxWidth="2500.0" prefWidth="75.0" text="Qte Commande" />
<TableColumn fx:id="col_prix_vent" maxWidth="3000.0" prefWidth="75.0" text="Prix Vent" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
Your getter/setter methods getN_art1 and setN_art1 should be named getDes_art1 and setDes_art1, respectively. PropertyValueFactory<> searches for getters named getNameOfProperty.
See PropertyValueFactory<> documentation for details.

How to connect TableCell control with underlying row model in javafx?

I am using a TableView which is populated by my model.
I want to use a spinner control in one column.
I am able to create the spinner in the cells in the desired column,
but I am struggling to bind the spinners value to the models property.
This is the fxml
<ScrollPane>
<content>
<TableView prefHeight="525.0" prefWidth="814.0">
<columns>
<TableColumn prefWidth="75.0">
<cellValueFactory><PropertyValueFactory property="state"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Side">
<cellValueFactory><PropertyValueFactory property="side"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Source">
<cellValueFactory><PropertyValueFactory property="sourceContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Reference">
<cellValueFactory><PropertyValueFactory property="referenceContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Destination">
<cellValueFactory><PropertyValueFactory property="destinationContract"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Margin" editable="true">
<cellFactory><SpinnerTableCellFactory /></cellFactory>
<cellValueFactory><PropertyValueFactory property="margin"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Bot">
<cellValueFactory><PropertyValueFactory property="bot"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Price">
<cellValueFactory><PropertyValueFactory property="price"/></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="75.0" text="Volume">
<cellValueFactory><PropertyValueFactory property="volume"/></cellValueFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<GridRowModel state="false" side="BID" sourceContract="s01" referenceContract="" destinationContract="d01" margin="0" bot="MinMax" price="15.125" volume="0" />
<GridRowModel state="false" side="ASK" sourceContract="s02" referenceContract="" destinationContract="d02" margin="0" bot="MinMax" price="15.125" volume="0" />
</FXCollections>
</items>
</TableView>
</content>
</ScrollPane>
And this is the SpinnerTableCellFactory
public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> {
#Override
public TableCell<S, Double> call(TableColumn<S, Double> param) {
return new TableCell<S, Double>() {
Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d);
protected void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setText(null);
setGraphic(null);
} else {
spinner.getValueFactory().setValue(getItem());
setText(null);
setGraphic(spinner);
}
}
};
};
}
}
When the fxml is loaded the updateItem method is called with the default values from the fxml for the margin property. I can see and use the spinner in the cells. But how do I pass any new spinner value back to the margin property in the GridRowModel object?
Just register a listener with the spinner's valueProperty():
public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> {
#Override
public TableCell<S, Double> call(TableColumn<S, Double> param) {
return new TableCell<S, Double>() {
Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d);
{
spinner.valueProperty().addListener((obs, oldValue, newValue) -> {
ObservableValue<Double> value = getTableColumn().getCellObservableValue(getIndex());
if (value instanceof WritableValue) {
((WritableValue<Double>)value).setValue(newValue);
}
});
}
protected void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setText(null);
setGraphic(null);
} else {
spinner.getValueFactory().setValue(getItem());
setText(null);
setGraphic(spinner);
}
}
};
};
}
}
I'm assuming here that your model class GridRowModel follows the JavaFX properties pattern.
If you don't use JavaFX Properties, or want to avoid the cast, you can give the cell factory a BiConsumer<GridRowModel, Double> to process updates:
public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> {
private BiConsumer<S, Double> updater = null ;
public void setUpdater(BiConsumer<S, Double> updater) {
this.updater = updater ;
}
#Override
public TableCell<S, Double> call(TableColumn<S, Double> param) {
return new TableCell<S, Double>() {
Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d);
{
spinner.valueProperty().addListener((obs, oldValue, newValue) -> {
if (updater != null) {
updater.accept(getTableView().getItems().get(getIndex()), newValue);
}
});
}
protected void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setText(null);
setGraphic(null);
} else {
spinner.getValueFactory().setValue(getItem());
setText(null);
setGraphic(spinner);
}
}
};
};
}
}
Then you can add a fx:id to your factory:
<cellFactory><SpinnerTableCellFactory fx:id="marginCellFactory" /></cellFactory>
and in your controller do:
#FXML
private SpinnerTableCellFactory<GridRowModel, Double> marginCellFactory ;
public void initialize() {
marginCellFactory.setUpdater(GridRowModel::setMargin);
}

JavaFX : data isn't displayed in tableview's column when trying to use cellfactory

I want to display data in tableview's column with custom rendering. I tried to adapt this tuto to my need.
Problem :
In the code example below, when I use the setCellFactory() method, the data in the corresponding column isn't displayed.
You can comment or uncomment the delimited section to see what happen in controller class.
Main class
public class CellFactory extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = FXMLLoader.load(CellFactory.class.getResource("CellFactory_Layout.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("CellFactory EXAMPLE");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Model class
public class Fruit {
private final SimpleStringProperty name;
private final SimpleIntegerProperty weight;
public Fruit(String name, int weight){
this.name = new SimpleStringProperty(name);
this.weight = new SimpleIntegerProperty(weight);
}
public String getName() {return this.name.get();}
public void setName(String v) {this.name.set(v);}
public SimpleStringProperty nameProperty() {return this.name;}
public int getWeight() {return this.weight.get();}
public void setWeight(int v) {this.weight.set(v);}
public SimpleIntegerProperty weightProperty() {return this.weight;}
}
Controller class
public class CellFactory_Controller implements Initializable {
#FXML private TableView<Fruit> fruit_tbl;
#FXML private TableColumn<Fruit, String> name_cln;
#FXML private TableColumn<Fruit, Integer> weight_cln;
// array with table data
final ObservableList<Fruit> data = FXCollections.observableArrayList();
public CellFactory_Controller() {
// some data
this.data.add(new Fruit("banana", 120));
this.data.add(new Fruit("apple", 150));
this.data.add(new Fruit("coconut", 500));
this.data.add(new Fruit("orange", 200));
}
#Override
public void initialize(URL location, ResourceBundle resources) {
this.name_cln.setCellValueFactory(new PropertyValueFactory<>("name"));
this.weight_cln.setCellValueFactory(new PropertyValueFactory<>("weight"));
this.weight_cln.setCellValueFactory(cellData -> cellData.getValue().weightProperty().asObject());
// comment or uncomment to see what happen
///////////////////////////////////////////////////////////////////////
this.weight_cln.setCellFactory(column -> new TableCell<Fruit, Integer>() {
#Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
if (item < 10) {
setTextFill(Color.CHOCOLATE);
} else {
setTextFill(Color.BLACK);
setStyle("");
}
}
}
});
///////////////////////////////////////////////////////////////////////
this.fruit_tbl.setItems(this.data);
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="CellFactory.CellFactory_Controller">
<children>
<TableView fx:id="fruit_tbl" layoutX="189.0" layoutY="93.0" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columns>
<TableColumn fx:id="name_cln" prefWidth="471.0" text="FRUIT" />
<TableColumn fx:id="weight_cln" prefWidth="75.0" text="WEIGHT" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</AnchorPane>
Question :
From my code example, how can I use custom cell renderer properly (with int data type) to display my data ?
you forgot to add the following statement:
setText(String.valueOf(item));
So, your setCellFactory() method should look like the following:
this.weight_cln.setCellFactory(column -> new TableCell<Fruit, Integer>() {
#Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
setText(String.valueOf(item));
if (item < 200) {
setTextFill(Color.CHOCOLATE);
} else {
setTextFill(Color.BLACK);
}
}
}
});

How can I create my own icon with propertise in JavaFX

Maybe somebody knows the answer and try help me.
I am creating own button.
<fx:root maxHeight="100.0" maxWidth="100.0" minHeight="50.0" minWidth="50.0" prefHeight="80.0" prefWidth="80.0" style="-fx-background-color: red;" type="StackPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
<children>
<ImageView fx:id="baseImage" fitHeight="66.0" fitWidth="72.0" pickOnBounds="true" preserveRatio="true" StackPane.alignment="TOP_CENTER" />
<Label fx:id="textBtn" alignment="BOTTOM_LEFT" prefHeight="17.0" prefWidth="75.0" textFill="WHITE" textOverrun="CLIP" StackPane.alignment="BOTTOM_LEFT" />
</children>
</fx:root>
So I need to change my button (Image and Label), when I am creating this in FXML file.
<MyButton layoutX="200.0" layoutY="162.0" />
e.g
<MyButton layoutX="200.0" layoutY="162.0" image="" text="" />
Can somebody help me ?
My Java Code
public class MyButton extends StackPane
{
#FXML
private ImageView baseImage;
#FXML
private Label textBtn;
public MyButton()
{
FXMLLoader fxmlLoader =new FXMLLoader(getClass().getResource("/pl/edu/wat/wcy/pz/icons/MyButtonView.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setRoot(this);
init();
try {
fxmlLoader.load();
}
catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public Label getTextBtn() {
return textBtn;
}
public void setTextBtn(Label textBtn) {
this.textBtn = textBtn;
}
public ImageView getBaseImage() {
return baseImage;
}
public void setBaseImage(Image location) {
this.baseImage.setImage(location);
}
public void setButton(Label textBtn, Image location){
this.baseImage.setImage(location);
this.textBtn = textBtn;
}
But I care about icon are changed in FXML file, not JavaCode
}
If you want to set properties in FXML:
<MyButton layoutX="200.0" layoutY="162.0" image="" text="" />
you must define those properties in the corresponding class. In particular, MyButton must define setImage(...) and setText(...) methods (it already has setLayoutX(...) and setLayoutY(...) which are inherited from StackPane). It's hard to know exactly what functionality you want here, but you probably want to set these up as JavaFX Properties. If the intention is to map these into the Label and ImageView defined in the FXML file, you can just expose the relevant properties from the controls. You might need to work a bit to map the string from the image property into the correct thing.
public class MyButton extends StackPane
{
#FXML
private ImageView baseImage;
#FXML
private Label textBtn;
public MyButton()
{
FXMLLoader fxmlLoader =new FXMLLoader(getClass().getResource("/pl/edu/wat/wcy/pz/icons/MyButtonView.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setRoot(this);
// not sure what this is:
// init();
// note that if you define
// public void initialize() {...}
// it will be called
// automatically during the FXMLLoader.load() method
try {
fxmlLoader.load();
}
catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public StringPropergty textProperty() {
return textBtn.textProperty();
}
public final String getText() {
return textProperty().get();
}
public final void setText(String text) {
textProperty().set(text);
}
// similarly expose a property for image, but you need to be able to coerce it from a String
}
(Incidentally, I assume this is just an example for the purposes of understanding how to do this. Everything you have in the example can be done using a regular button. Just wanted to make that clear for any others reading this post.)

Resources