Why member is not injected in JavaFX controller? - java

I have the following FXML:
<BorderPane fx:controller="mypackage.MainStage" id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<bottom>
<ToolBar>
<items>
<Slider id="slider" prefWidth="443.0" />
<Label text="Record:" />
<TextField prefWidth="46.0" />
<Label text=" of " />
<Label id="totalLabel" text="0" />
</items>
</ToolBar>
</bottom>
<center>
<Pane id="mainPane" prefHeight="200.0" prefWidth="200.0" />
</center>
<top>
<ToolBar>
<items>
<Button mnemonicParsing="false" text="Load more" />
</items>
</ToolBar>
</top>
</BorderPane>
and the following controller code:
public class MainStage implements Initializable {
#FXML
private Pane mainPane;
#FXML
private Label totalLabel;
#Override
public void initialize(URL location, ResourceBundle resources) {
totalLabel.setText("245");
}
}
and the following application code
public class MyClass extends Application
{
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("MainStage.fxml"));
Scene scene = new Scene(root);
stage.setTitle("MyClass");
stage.setScene(scene);
stage.show();
}
public static void main( String[] args )
{
launch(args);
}
}
If I set breakpoint to initialize() I see it is called, but member is null.
Why isn't it injected?

Because I used id while was to use fx:id tag.

Related

JavaFX TableView - Unable to display rows

Working on a Simple Invoice Software for self. Got stuck at the first point.
Unable to display rows in Tableview. I have tried every possible solution, gone through many tutorial videos, guides etc. Still not able to find the problem
Please help
NewInvoice.fxml
<TabPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<tabs>
<Tab text="CASH">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="additembutton" layoutX="412.0" layoutY="41.0" mnemonicParsing="false" text="ADD" />
<TableView fx:id="invoiceitemtableview" layoutX="190.0" layoutY="180.0" prefHeight="200.0" prefWidth="481.0">
<columns>
<TableColumn fx:id="amountcol" prefWidth="75.0" text="Amount" />
<TableColumn fx:id="gstcol" prefWidth="75.0" text="GST" />
<TableColumn fx:id="subtotalcol" prefWidth="75.0" text="Subtotal" />
<TableColumn fx:id="cgstcol" prefWidth="75.0" text="CGST" />
<TableColumn fx:id="sgstcol" prefWidth="75.0" text="SGST" />
</columns>
</TableView>
<TextField fx:id="itemcodetextbox" layoutX="216.0" layoutY="41.0" />
</children></AnchorPane>
</content>
</Tab>
<Tab text="BOBCARD">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
NewInvoiceController.java
public class NewInvoiceController implements Initializable {
#FXML
TableView<InvoiceItemBean> invoiceitemtableview;
#FXML
TableColumn<InvoiceItemBean,String> amountcol, gstcol, subtotalcol, cgstcol, sgstcol;
final ObservableList<InvoiceItemBean> data = FXCollections.observableArrayList(
new InvoiceItemBean("1049","5","999.10","22.5","22.5"),
new InvoiceItemBean("1800","12","1180.10","305.00","305.00")
);
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
amountcol.setCellValueFactory(new PropertyValueFactory<>("amount"));
gstcol.setCellValueFactory(new PropertyValueFactory<>("gst"));
subtotalcol.setCellValueFactory(new PropertyValueFactory<>("subtotal"));
cgstcol.setCellValueFactory(new PropertyValueFactory<>("cgst"));
sgstcol.setCellValueFactory(new PropertyValueFactory<>("sgst"));
invoiceitemtableview.setItems(data);}
}
InvoiceItemBean.java
public class InvoiceItemBean {
private final SimpleStringProperty amount;
private final SimpleStringProperty gst;
private final SimpleStringProperty subtotal;
private final SimpleStringProperty cgst;
private final SimpleStringProperty sgst;
public InvoiceItemBean( String amount, String gst, String subtotal, String cgst, String sgst) {
this.amount = new SimpleStringProperty(amount);
this.gst = new SimpleStringProperty(gst);
this.subtotal = new SimpleStringProperty(subtotal);
this.cgst = new SimpleStringProperty(cgst);
this.sgst = new SimpleStringProperty(sgst);
}
public String getAmount() {
return amount.get();
}
public String getGst() {
return gst.get();
}
public String getSubtotal() {
return subtotal.get();
}
public String getCgst() {
return cgst.get();
}
public String getSgst() {
return sgst.get();
}
public void setAmount(String amount_value) {
amount.set(amount_value);
}
public void setGst(String gst_value) {
gst.set(gst_value);
}
public void setSubtotal(String subtotal_value) {
subtotal.set(subtotal_value);
}
public void setCgst(String cgst_value) {
cgst.set(cgst_value);
}
public void setSgst(String sgst_value) {
sgst.set(sgst_value);
}
}
Main.java
public class ClimaxInvoice extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("NewInvoice.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Unable to get anything
Output Table view showing no content
PLEASE HELP!!!
Your problem is really simple, you haven't specified the controller in the fxml.
Just add fx:controller="packageName.NewInvoiceController"
at the end of the first line in your fxml file.
So the whole line should be:
<TabPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="packageName.NewInvoiceController">
Of course, replace packageName with the name of your package.

Can't pass attribute betwewen scenes JAvaFX

I'm trying to pass a String between scenes in JavaFX, I already followed the some answers but it seems that they don't work because the string is null in the new scene.
Here's my MainControler:
public class FXMLDocumentController implements Initializable {
#FXML
private Button btn_signup;
#FXML
private TextField et_username;
#FXML
private PasswordField et_password;
#FXML
private Hyperlink link_login;
Stage prevStage;
public void setPrevStage(Stage stage){
this.prevStage = stage;
}
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
if(btn_signup == event.getSource()){
Conector conn = new Conector();
if (conn.checkUser(et_username.getText(), et_password.getText())) {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource("FXMLTasker.fxml"));
Pane myPane = (Pane)myLoader.load();
Scene scene = new Scene(myPane);
Stage stage = new Stage();
stage.setResizable(false);
stage.setScene(scene);
FXMLTaskerController controler = new FXMLTaskerController();
controler.setUser(et_username.getText());
myLoader.setController(controler);
prevStage.close();
stage.show();
}else {
JOptionPane.showMessageDialog(null, "Usuario o ContraseƱa incorrecta");
}
}else if (link_login == event.getSource()){
System.out.println("Registrate!");
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Here's the other class controler, the one where i want my String.
public class FXMLTaskerController implements Initializable {
#FXML private ListView list_todo;
#FXML private ListView list_done;
#FXML public String username;
private void handleButtonAction(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
System.out.println(username);
list_todo.setCellFactory(new TaskCellFactory());
list_done.setCellFactory(new TaskCellFactory());
try {
getTasks();
} catch (IOException ex) {
Logger.getLogger(FXMLTaskerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setUser(String username){
this.username = username;
}
public void getTasks() throws IOException{
Conector con = new Conector();
for(Task task: con.obtenerTareas("pepin")){
System.out.println(task);
if(task.isState()){
list_done.getItems().add(task);
}else{
list_todo.getItems().add(task);
}
}
}
}
And here are the fxml files:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="400.0" prefWidth="500.0" style="-fx-background-color: #0288D1; -fx-border-color: #01579B; -fx-border-width: 5;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLDocumentController">
<children>
<Label layoutX="215.0" layoutY="34.0" text="Sign In" textFill="WHITE">
<font>
<Font size="23.0" />
</font>
</Label>
<Hyperlink fx:id="link_login" layoutX="150.0" layoutY="269.0" onAction="#handleButtonAction" text="Not registered yet? Click here." textFill="WHITE" />
<TextField fx:id="et_username" layoutX="21.0" layoutY="102.0" prefHeight="25.0" prefWidth="425.0" promptText="Username" style="-fx-prompt-text-fill: #ffffff; -fx-background-color: #0288D1;" />
<Separator layoutX="27.0" layoutY="126.0" prefHeight="3.0" prefWidth="425.0" />
<Separator layoutX="27.0" layoutY="192.0" prefHeight="3.0" prefWidth="425.0" />
<Button fx:id="btn_signup" layoutX="27.0" layoutY="222.0" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="23.0" prefWidth="425.0" style="-fx-background-color: #FFA000; -fx-prompt-text-fill: #ffffff;" text="SignUp" textFill="WHITE" />
<PasswordField fx:id="et_password" layoutX="21.0" layoutY="167.0" prefHeight="25.0" prefWidth="425.0" promptText="Password" style="-fx-background-color: #0288D1; -fx-prompt-text-fill: #ffffff;" />
</children>
</AnchorPane>
And the other one:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLTaskerController">
<children>
<SplitPane dividerPositions="0.5811881188118811" layoutX="-8.0" layoutY="35.0" prefHeight="529.0" prefWidth="1027.0" style="-fx-background-color: #EEEEEE;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_todo" layoutY="-8.0" prefHeight="527.0" prefWidth="584.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_done" layoutY="14.0" prefHeight="527.0" prefWidth="420.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
</items>
</SplitPane>
<MenuBar prefHeight="30.0" prefWidth="1012.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
As you can see I tried to use a controler and using a set pasing the String, the problem is that when I open the new scene, his controler resets and the String is no longer there, any idea why or how to solve this?
If you want to set a Controller with myLoader.setController(controler); you must do it before calling Pane myPane = (Pane)myLoader.load(); and also remove fx:controller="desktop_tasker.FXMLTaskerController" from FXMLTasker.fxml, else you get a LoadException: Controller value already specified.
See JavaDoc FXMLLoader.setController(Object controller):
Sets the controller associated with the root object. The value passed to this method is used as the value of the fx:controller attribute. This method must be called prior to loading the document when using controller event handlers when an fx:controller attribute is not specified in the document.
Alternatively you can request the Controller from FXMLLoader:
FXMLTaskerController controler = (FXMLTaskerController)myLoader.getController();
controler.setUser(et_username.getText());
But thereby you can't assume that username is set in initialize(URL url, ResourceBundle rb) and should removed from there.

Accessing controls of a controller from another controller in javafx

I am building an simple javafx application using afterburner. I have main window which have a border pane and it's upper part contains menus and in center it have a vertical split pane which have two anchor panes with fx:id=inputPane and fx:id=tablePane. Now in inputPane i am loading different scenes and submitting data from it into tablePane.
Now i have a scene opened in inputPane which have a button and i want to submit the data from this scene into table as well as i want to open an another scene into inputPane and again want to submit it's data into table.
adara.fxml
<BorderPane fx:id="mainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="180.0" minWidth="-Infinity" prefHeight="507.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.qaf.presentation.adara.AdaraPresenter">
<top>
<Pane prefHeight="26.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
<MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="800.0">
<menus>
<Menu mnemonicParsing="false" text="Stock">
<items>
<MenuItem fx:id="createStock" mnemonicParsing="false" onAction="#showCreateStockForm" text="Create" />
<MenuItem fx:id="incoming" mnemonicParsing="false" onAction="#showIncomingForm" text="Incoming" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</Pane>
</top>
<center>
<SplitPane dividerPositions="0.5" orientation="VERTICAL" prefHeight="469.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<items>
<BorderPane fx:id="contentBorderPane" prefHeight="200.0" prefWidth="200.0">
<center>
<AnchorPane fx:id="contentBox" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
<AnchorPane fx:id="tableBox" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" />
</items>
</SplitPane>
</center>
</BorderPane>
adaraView.java
public class AdaraView extends FXMLView {
}
adaraPresenter.java
public class AdaraPresenter implements Initializable {
#FXML
AnchorPane contentBox;
#FXML
AnchorPane tableBox;
StockCreationPresenter stockCreationPresenter;
InwardsPresenter inwardsPresenter;
ViewStockPresenter viewStockPresenter;
#Override
public void initialize(URL location, ResourceBundle resources) {
StockCreationView scView = new StockCreationView();
// other codes
.
.
ViewStockView vsView = new ViewStockView();
// other codes
.
.
contentBox.getChildren().add(scView.getView());
tableBox.getChildren().add(vsView.getView());
}
public void showCreateStockForm(){
StockCreationView scView = new StockCreationView();
// other codes
.
.
ViewStockView vsView = new ViewStockView();
// other codes
.
.
contentBox.getChildren().add(scView.getView());
tableBox.getChildren().add(vsView.getView());
}
public void showIncomingForm(){
InwardsView inView = new InwardsView();
// other codes
.
.
ViewStockView vsView = new ViewStockView();
// other codes
.
.
contentBox.getChildren().add(inView.getView());
tableBox.getChildren().add(vsView.getView());
}
}
Here is the main class which is starting the stage and application.
Main.java
public class App extends Application
{
#Override
public void start(Stage stage) throws Exception {
AdaraView appView = new AdaraView();
Scene scene = new Scene(appView.getView());
stage.setTitle("Adara");
final String uri = getClass().getResource("app.css").toExternalForm();
scene.getStylesheets().add(uri);
stage.setScene(scene);
stage.show();
}
#Override
public void stop() throws Exception {
Injector.forgetAll();
}
public static void main(String[] args) {
launch(args);
}
}
Now here is the InwardsPresenter.java which have to save the stockCreationPresenter.java data into table as well as it have to open the inwardsView into the contentPane.
InwardsPresenter.java
public class InwardsPresenter implements Initializable {
#FXML
Button saveButton;
#FXML
TextField orderNo;
#FXML
TextField other;
#FXML
CheckBox save;
#Inject
AdaraPresenter adaraPresenter;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void save() {
Inwards inward = newInward();
inward.setOrderNo(Integer.parseInt(orderNo.getText()));
inward.setOther(other.getText());
inward.setSave(save.isSelected());
this.newInward.set(inward);
adaraPresenter.incomingForm();
}
}
// while executing adaraPresenter.incomingForm(); it's showing NPE to contentBox and tableBox.
Thank you very much for any help.

JavaFXML include FXML change upper controller

I have a small question.
I have a Menu.FXML which has a Controller (MenuController).
Inside the Menu.FXML I Include another .FXMl (Inner.FXML) and it includes a Label.
The Inner.FXML has a MouseClick event handler, so when I Click the Inner.FXML it does something, I want my Inner.FXML mouse listener to change the text which is inside the Menu.FXML.
How can I do this?
Thank you very much.
[CODE]
public class Main extends Application{
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Menu.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
InnerController:
public class InnerController implements Initializable {
public void buttonClick(ActionEvent event){
System.out.println("change label!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Menu FXML:
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nestedcontroller.MenuController">
<children>
<Label text="Label" />
<fx:include source="Inner.fxml" />
</children>
</VBox>
InnerFXML.
<Pane fx:id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: green;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nestedcontroller.InnerController">
<children>
<Button layoutX="271.0" layoutY="187.0" mnemonicParsing="false" onAction="#buttonClick" text="Button" />
</children>
</Pane>
Create and observable string property in the InnerContoller and set it from the button's handler. Then observe the property from the outer controller.
public class InnerController {
private final ReadOnlyStringWrapper text = new ReadOnlyStringWrapper();
public ReadOnlyStringProperty textProperty() {
return text.getReadOnlyProperty() ;
}
public String getText() {
return text.get();
}
public void buttonClick(ActionEvent event){
System.out.println("change label!");
text.set("Hello world");
}
public void initialize() {
}
}
Then add an fx:id to your fx:include:
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nestedcontroller.MenuController">
<children>
<Label text="Label" fx:id="label" />
<fx:include source="Inner.fxml" fx:id="innerPane" />
</children>
</VBox>
And then in the MenuController just observe the property:
public class MenuController {
#FXML
private Label label ;
#FXML
private InnerController innerPaneController ;
public void initialize() {
innerPaneController.textProperty().addListener((obs, oldText, newText) ->
label.setText(newText));
// or just label.textProperty().bind(innerPaneController.textProperty());
}
}
See the FXML documentation for details.

Edit the values of the TableView from TextField

Hi I am trying in the spirit of the example in http://code.makery.ch/java/javafx-2-tutorial-intro/ to make a similar application where the TableView values can be edited by a series of TextFields instead of a popup form. The reason why I would wannt do it like that is that I am having many fields in a similar application I want to develop and I would like to avoid the user editing them on the TableView
The TableView shows a list of Persons where for each I record name, surname and country. I have tried to create a bidirectionalBinding between the name property of the Person bean and the textProperty() of the TextField but this doesn't work.
I also tried to add to the textProperty a ChangeListener so when it changes to update the ObservableList of propoerties and this also didn't work
Apparently I am doing something wrong and so far I have the following code:
FXDocumentController.java
public class FXMLDocumentController implements Initializable {
private static final Logger logger = Logger.getLogger(FXMLDocumentController.class.getName());
private ObservableList<Person> data;
#FXML
private TableView<Person> tableview;
#FXML
private TableColumn<Person, String> colName;
#FXML
private TableColumn<Person, String> colSurname;
#FXML
private TableColumn<Person, String> colCountry;
#FXML
private TextField name;
#Override
public void initialize(URL url, ResourceBundle rb) {
assert tableview != null : "fx:id=\"tableview\" was not injected: check your FXML file 'UserMaster.fxml'.";
colName.setCellValueFactory(
new PropertyValueFactory<Person,String>("name"));
colSurname.setCellValueFactory(
new PropertyValueFactory<Person,String>("surname"));
colCountry.setCellValueFactory(
new PropertyValueFactory<Person,String>("country"));
DBClass objDbClass = new DBClass();
try{
con = objDbClass.getConnection();
buildData();
tableview.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 1) {
Person p = tableview.getSelectionModel().getSelectedItem();
//name.textProperty().setValue(p.getName());
name.textProperty().bindBidirectional(p.name);
//name.textProperty().bind(p.name);
}
}
}
});
name.textProperty().addListener(new ChangeListener(){
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
System.out.println("Value changed!");
/** Tried also this but this wont work
name.textProperty().setValue((String)t1);
int index = tableview.getSelectionModel().getSelectedIndex();
data.get(index).name.setValue( (String) t1);
tableview.setItems(data);
* */
}
}
);
}
catch(ClassNotFoundException ce){
logger.info(ce.toString());
}
catch(SQLException ce){
logger.info(ce.toString());
}
} //initialize
private void buildData() {
data = FXCollections.observableArrayList();
try{
data.add(new Person("Jon", "Doe", "USA"));
data.add(new Person("Lars", "Andersson", "Sweden"));
tableview.setItems(data);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
}
Person.java
public class Person {
public SimpleStringProperty name = new SimpleStringProperty();
public SimpleStringProperty surname = new SimpleStringProperty();
public SimpleStringProperty country = new SimpleStringProperty();
public Person(String name, String surname, String country){
this.name.set(name);
this.surname.set(surname);
this.country.set(country);
}
public String getName(){
return name.get();
}
public String getSurname(){
return surname.get();
}
public String getCountry(){
return country.get();
}
}
And for the sake of completeness I am giving the fxml file (very ugly but I am experimenting with the functionality;)) and the launcher
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" blendMode="SRC_OVER" cache="false" disable="false" focusTraversable="false" prefHeight="576.0" prefWidth="1024.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="javafxdemoproject.FXMLDocumentController">
<children>
<SplitPane dividerPositions="0.3336594911937378" focusTraversable="true" layoutX="0.0" layoutY="55.0" prefHeight="521.0" prefWidth="1024.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="410.0" prefWidth="297.0">
<children>
<TableView fx:id="tableview" editable="true" prefHeight="520.0" prefWidth="338.0" tableMenuButtonVisible="true" AnchorPane.bottomAnchor="178.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columns>
<TableColumn prefWidth="75.0" text="Name" fx:id="colName" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="154.0" text="Surname" fx:id="colSurname" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="112.0" text="Country" fx:id="colCountry" />
</columns>
</TableView>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="404.0" prefWidth="460.0">
<children>
<Accordion layoutX="0.0" layoutY="0.0" prefHeight="520.0" prefWidth="262.0">
<expandedPane>
<TitledPane fx:id="personalTp" animated="false" text="Personal Details">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField fx:id="name" layoutX="44.0" layoutY="27.0" prefWidth="200.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</expandedPane>
<panes>
<fx:reference source="personalTp" />
<TitledPane fx:id="x2" animated="false" text="Positions held">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<ListView prefHeight="621.0" prefWidth="454.0" AnchorPane.bottomAnchor="-2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="74.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</AnchorPane>
</items>
</SplitPane>
<MenuBar layoutY="0.0" AnchorPane.rightAnchor="908.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<ToolBar layoutY="24.0" AnchorPane.leftAnchor="0.0">
<items>
<Button mnemonicParsing="false" text="Button" />
</items>
</ToolBar>
</children>
</AnchorPane>
JavaFXDemoProject.java
public class JavaFXDemoProject extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Questions
1) Is it at all possible what I am trying to do?
2) Why isn't this working with bidirectionalBinding
Any help appreciated
I changed your controller class like this
public void initialize(URL url, ResourceBundle rb) {
assert tableview != null : "fx:id=\"tableview\" was not injected: check your FXML file 'UserMaster.fxml'.";
colName.setCellValueFactory(
new PropertyValueFactory<Person,String>("name"));
colSurname.setCellValueFactory(
new PropertyValueFactory<Person,String>("surname"));
colCountry.setCellValueFactory(
new PropertyValueFactory<Person,String>("country"));
buildData();
tableview.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Person>() {
#Override
public void changed(ObservableValue<? extends Person> observable, Person oldValue, Person newValue) {
if (oldValue !=null) name.textProperty().unbindBidirectional(oldValue.nameProperty());
if (newValue !=null) name.textProperty().bindBidirectional(newValue.nameProperty());
}
});
} //initialize
and your person class a bit
public class Person {
private StringProperty name = new SimpleStringProperty();
private StringProperty surname = new SimpleStringProperty();
private StringProperty country = new SimpleStringProperty();
public Person(String name, String surname, String country){
this.name.set(name);
this.surname.set(surname);
this.country.set(country);
}
public StringProperty nameProperty(){return name;}
public StringProperty surnameProperty(){return surname;}
public StringProperty countryProperty(){return country;}
}
Now the TextField can bind to the property in Person

Categories