Basically I have tableview and a FORM. I enter value in the form and they are displayed inside the table view via a database. It looks like this: FORM and TableView
When I click on the row to select it , I want to retrieve the DatePicker value from the column Begin Datum back to the Datepicker field.
I have a onMouseClicked method like this to retrieve the text/vlaues from the selected row back to the FORM
#FXML
void getSelected(MouseEvent event) {
index = tableViewBooking.getSelectionModel().getSelectedIndex();
if (index <= -1) {
return;
}
beginTime.setText(tableColSTime.getCellData(index).toString());
endTime.setText(tableColETime.getCellData(index).toString());
beginDate.setValue(tableColDate.getCellData(index).toString()); // problem has somewith with `toString()?`
reminderDesc.setText(tableColName.getCellData(index).toString());
}
Relevant primaryController code:
public class PrimaryController {
ObservableList<String> intervalList =
FXCollections.observableArrayList("Täglich","Wochelich","Monatlich");
ObservableList<String> projectTypeList = FXCollections.observableArrayList("ProjeKt Iot","Projekt Data & Analytics","Projekt SAP Intelligent Enterprise",
"Projekt Prozess & Betrieb"," Projekt Moderne Software Architekturen ");
#FXML
private DatePicker beginDate;
#FXML
private TextField beginTime;
#FXML
private Button clearButton;
#FXML
private DatePicker endDate;
#FXML
private TextField endTime;
#FXML
private TextField reminderDesc;
#FXML
private Button saveButton;
#FXML
private ComboBox cycleComboBox;
#FXML
private ComboBox projectComboBox;
#FXML
private JFXListView<String> listofdata;
#FXML
private Button modifyButton;
#FXML
private ResourceBundle resources;
#FXML
private URL url;
// Table View
#FXML
public TableView<Booking> tableViewBooking;
#FXML
public TableColumn<Booking, String> tableColName;
#FXML
public TableColumn<Booking, Double> tableColHours;
#FXML
public TableColumn<Booking, String> tableColType;
// #FXML
// public TableColumn<Booking, String> tableColProj;
#FXML
public TableColumn<Booking, String> tableColDate;
#FXML
public TableColumn<Booking, String> tableColSTime;
#FXML
public TableColumn<Booking, String> tableColETime;
int index = -1 ;
#FXML
public void initialize() throws IOException, ParseException {
cycleComboBox.setValue("Täglich");
cycleComboBox.setItems(intervalList);
projectComboBox.setValue("Projekt Moderne Software Architekturen ");
projectComboBox.setItems(projectTypeList);
System.out.println("Inside initialize");
tableColName.setCellValueFactory(new PropertyValueFactory<>("Name"));
tableColDate.setCellValueFactory(new PropertyValueFactory<>("Date"));
tableColSTime.setCellValueFactory(new PropertyValueFactory<>("startTime"));
tableColETime.setCellValueFactory(new PropertyValueFactory<>("endTime"));
tableColHours.setCellValueFactory(new PropertyValueFactory<>("Hours"));
tableColType.setCellValueFactory(new PropertyValueFactory<>("Type"));
tableViewBooking.setItems(getTableBookings());
}
the problem here is that String is undefined type for Datepicker, it is LocalDate . So what to use here instead of .toString()?
beginDate.setValue(tableColDate.getCellData(index).toString());
You should either make the tableColDate be TableColumn<Booking, LocalDate>. Then you can remove the toString() call and everything works.
The reason is that setValue() expects a LocalDate, not a String.
Or you parse the date when you are setting the DatePicker: beginDate.setValue(LocalDate.parse(tableColDate.getCellData(index))).
Related
I am implementing a User Interface for a restaurant menu that involves a large number of increment and decrement buttons as shown below - please note I have used SceneBuilder to create the UI:
I have tried numerous methods to allow looping through each button and updating the text field next to it on mouse click but have failed to implement this via an arrayList - i keep receiving a null pointer error when i know the arraylist is succesfully filling up with the buttons.
Here is what I have tried:
I have a method which fills up the list by specifying the fxids of the appropriate buttons as so -
plusButtonList.add(soupPlus);
plusButtonList.add(guacPlus);
plusButtonList.add(empanadaPlus);
plusButtonList.add(jalapenoPlus);
plusButtonList.add(quesaPlus);
I also then have a method which is supposed to iterate through each of these buttons, setting the onaction to retrieve the current counter value from the textfield (which is also in a list but the corresponding button and text fields will be at the same indexed position) this method is called in 'initialise' in the controller class.
private void checkIfIncrement() {
for(int i = 0; i < 20; i++) {
int counter = i;
plusButtonList.get(i).setOnAction(e -> {
int currentCountVal = foodCounterList.get(counter);
theTextFields.get(counter).setText(Integer.toString(currentCountVal+ 1));
foodCounterList.set(counter, currentCountVal+1);
});
}
NOTE: foodCounterList is a list of integers containing each text field's current value. 'theTextFields' is the list containing each of the text fields.
UPDATE: Here is my Controller Class after attempting to implement the suggested improvement by Matt.
package customer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
/**
* View for the customer.
* #author Arslan Nazir
*
*/
public class CustomerView {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
#FXML
private ImageView imageview;
Stage stage;
#FXML
private Button soupPlus;
#FXML
private Button soupMinus;
#FXML
private TextField soupField;
#FXML
private Button guacMinus;
#FXML
private Button guacPlus;
#FXML
private TextField guacField;
#FXML
private Font x11322;
#FXML
private Button empanadaMinus;
#FXML
private TextField empanadaField;
#FXML
private Button empanadaPlus;
#FXML
private Button jalapenoMinus;
#FXML
private Button jalapenoPlus;
#FXML
private TextField jalapenoField;
#FXML
private Button quesaMinus;
#FXML
private Button quesaPlus;
#FXML
private TextField quesaField;
#FXML
private Button choriMinus;
#FXML
private Button choriPlus;
#FXML
private TextField choriField;
#FXML
private Button seafoodMinus;
#FXML
private Button seafoodPlus;
#FXML
private TextField seafoodField;
#FXML
private Button avocadoMinus;
#FXML
private Button avocadoPlus;
#FXML
private TextField avocadoField;
#FXML
private Button burritoMinus;
#FXML
private Button burritoPlus;
#FXML
private TextField burritoField;
#FXML
private Button chilliMinus;
#FXML
private Button chilliPlus;
#FXML
private TextField chilliField;
#FXML
private Font x113221;
#FXML
private Button churrosMinus;
#FXML
private Button churrosPlus;
#FXML
private TextField churrosField;
#FXML
private Button pastelMinus;
#FXML
private Button pastelPlus;
#FXML
private TextField pastelField;
#FXML
private Button brownieMinus;
#FXML
private Button browniePlus;
#FXML
private TextField brownieField;
#FXML
private Button strawbMinus;
#FXML
private Button strawbPlus;
#FXML
private TextField strawbField;
#FXML
private Button vanillaMinus;
#FXML
private Button vanillaPlus;
#FXML
private TextField vanillaField;
#FXML
private Font x11321;
#FXML
private Button colaPlus;
#FXML
private Button colaMinus;
#FXML
private TextField colaField;
#FXML
private Button dietColaMinus;
#FXML
private Button dietColaPlus;
#FXML
private TextField dietColaField;
#FXML
private Button mojitoMinus;
#FXML
private Button mojitoPlus;
#FXML
private TextField mojitoField;
#FXML
private Button blueMargMinus;
#FXML
private Button blueMargPlus;
#FXML
private TextField blueMargField;
#FXML
private Button redMargMinus;
#FXML
private Button redMargPlus;
#FXML
private TextField redMargField;
#FXML
private Button bottleWaterMinus;
#FXML
private Button bottleWaterPlus;
#FXML
private TextField bottleWaterField;
#FXML
private Button tapWaterMinus;
#FXML
private Button tapWaterPlus;
#FXML
private TextField tapWaterField;
#FXML
private Button closeprogram;
#FXML
private Button minimiseprogram;
#FXML
private VBox bgone;
#FXML
private Button callwaiter;
#FXML
private TextField summaryField;
static List<TextField> theTextFields = new ArrayList<>();
ArrayList<Button> plusButtonList = new ArrayList<>(Arrays.asList(soupPlus, guacPlus));
static List<Button> minusButtonList = new ArrayList<>();
static List<Integer> foodCounterList = new ArrayList<>();
public void listPopulate() {
theTextFields.add(soupField);
theTextFields.add(guacField);
theTextFields.add(empanadaField);
theTextFields.add(jalapenoField);
theTextFields.add(quesaField);
theTextFields.add(choriField);
theTextFields.add(seafoodField);
theTextFields.add(avocadoField);
theTextFields.add(burritoField);
theTextFields.add(chilliField);
theTextFields.add(churrosField);
theTextFields.add(pastelField);
theTextFields.add(brownieField);
theTextFields.add(strawbField);
theTextFields.add(vanillaField);
theTextFields.add(colaField);
theTextFields.add(dietColaField);
theTextFields.add(mojitoField);
theTextFields.add(blueMargField);
theTextFields.add(redMargField);
theTextFields.add(bottleWaterField);
theTextFields.add(tapWaterField);
for (int i = 0; i< theTextFields.size(); i++) {
theTextFields.get(i).setText("0");
}
minusButtonList.add(soupMinus);
minusButtonList.add(guacMinus);
minusButtonList.add(empanadaMinus);
minusButtonList.add(jalapenoMinus);
minusButtonList.add(quesaMinus);
minusButtonList.add(choriMinus);
minusButtonList.add(seafoodMinus);
minusButtonList.add(avocadoMinus);
minusButtonList.add(burritoMinus);
minusButtonList.add(chilliMinus);
minusButtonList.add(churrosMinus);
minusButtonList.add(pastelMinus);
minusButtonList.add(brownieMinus);
minusButtonList.add(strawbMinus);
minusButtonList.add(vanillaMinus);
minusButtonList.add(colaMinus);
minusButtonList.add(dietColaMinus);
minusButtonList.add(mojitoMinus);
minusButtonList.add(blueMargMinus);
minusButtonList.add(redMargMinus);
minusButtonList.add(bottleWaterMinus);
minusButtonList.add(tapWaterMinus);
/**
plusButtonList[0] = soupPlus;
plusButtonList[1] = guacPlus;
plusButtonList[2] = empanadaPlus;
plusButtonList[3] = soupPlus;
plusButtonList[4] = soupPlus;
plusButtonList[5] = soupPlus;
plusButtonList[6] = soupPlus;
plusButtonList[7] = soupPlus;
plusButtonList[8] = soupPlus;
plusButtonList[9] = soupPlus;
plusButtonList[10] = soupPlus;
plusButtonList[11] = soupPlus;
plusButtonList[12] = soupPlus;
plusButtonList[13] = soupPlus;
plusButtonList[14] = soupPlus;
plusButtonList[15] = soupPlus;
plusButtonList[16] = soupPlus;
plusButtonList[17] = soupPlus;
plusButtonList[18] = soupPlus;
plusButtonList[19] = soupPlus;
plusButtonList[20] = soupPlus;
plusButtonList[21] = soupPlus;
plusButtonList[22] = soupPlus;
plusButtonList.add(soupPlus);
plusButtonList.add(guacPlus);
plusButtonList.add(empanadaPlus);
plusButtonList.add(jalapenoPlus);
plusButtonList.add(quesaPlus);
plusButtonList.add(choriPlus);
plusButtonList.add(seafoodPlus);
plusButtonList.add(avocadoPlus);
plusButtonList.add(burritoPlus);
plusButtonList.add(chilliPlus);
plusButtonList.add(churrosPlus);
plusButtonList.add(pastelPlus);
plusButtonList.add(browniePlus);
plusButtonList.add(strawbPlus);
plusButtonList.add(vanillaPlus);
plusButtonList.add(colaPlus);
plusButtonList.add(dietColaPlus);
plusButtonList.add(mojitoPlus);
plusButtonList.add(blueMargPlus);
plusButtonList.add(redMargPlus);
plusButtonList.add(bottleWaterPlus);
plusButtonList.add(tapWaterPlus);
**/
foodCounterList.add(Integer.parseInt(soupField.getText()));
foodCounterList.add(Integer.parseInt(guacField.getText()));
foodCounterList.add(Integer.parseInt(empanadaField.getText()));
foodCounterList.add(Integer.parseInt(jalapenoField.getText()));
foodCounterList.add(Integer.parseInt(quesaField.getText()));
foodCounterList.add(Integer.parseInt(choriField.getText()));
foodCounterList.add(Integer.parseInt(seafoodField.getText()));
foodCounterList.add(Integer.parseInt(avocadoField.getText()));
foodCounterList.add(Integer.parseInt(burritoField.getText()));
foodCounterList.add(Integer.parseInt(chilliField.getText()));
foodCounterList.add(Integer.parseInt(churrosField.getText()));
foodCounterList.add(Integer.parseInt(pastelField.getText()));
foodCounterList.add(Integer.parseInt(brownieField.getText()));
foodCounterList.add(Integer.parseInt(strawbField.getText()));
foodCounterList.add(Integer.parseInt(vanillaField.getText()));
foodCounterList.add(Integer.parseInt(colaField.getText()));
foodCounterList.add(Integer.parseInt(dietColaField.getText()));
foodCounterList.add(Integer.parseInt(mojitoField.getText()));
foodCounterList.add(Integer.parseInt(blueMargField.getText()));
foodCounterList.add(Integer.parseInt(redMargField.getText()));
foodCounterList.add(Integer.parseInt(bottleWaterField.getText()));
foodCounterList.add(Integer.parseInt(tapWaterField.getText()));
}
private void checkIfIncrement() {
for (int i = 0; i < theTextFields.size(); i++) {
setButtonActionsForFoodItem(plusButtonList.get(i), theTextFields.get(i));
}
}
private void setButtonActionsForFoodItem(Button plusButton, TextField textField) {
plusButton.setOnAction(event -> {
int currentValue = Integer.parseInt(textField.getText());
textField.setText(String.valueOf(++currentValue));
});
}
/**for(int i =0; i < plusButtonList.size(); i++) {
int counter = i;
plusButtonList.get(i).setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
int currentCountVal = foodCounterList.get(counter);
theTextFields.get(counter).setText(Integer.toString(currentCountVal+ 1));
foodCounterList.set(counter, currentCountVal+1);
}
});
}**/
#FXML
private void handleCloseProgram(ActionEvent event) {
stage = (Stage)((Button)event.getSource()).getScene().getWindow();
stage.close();
System.exit(1);
}
#FXML
private void handleMinimiseProgram(ActionEvent event) {
stage = (Stage)((Button)event.getSource()).getScene().getWindow();
stage.setIconified(true);
}
#FXML
public void handle(ActionEvent event) {
}
#FXML
void initialize() {
//ButtonAndCountLists.setCounters();
listPopulate();
//System.out.println(plusButtonList.get(21));
System.out.println(foodCounterList.get(1));
checkIfIncrement();
}
}
First of all, I don't understand why you are using static lists in this solution? In that case I think they should be just marked as private.
Next I don't think that method "checkIfIncrement" has proper name for what it is doing. From your code I suppose it should be named setButtonsListeners()?
Did you put proper fx:id="exampleName" on increment/decrement buttons in you FXML file ? Maybe it is causing NPE. Please paste fxml file here with error stacktrace.
So I had a similar issue. I was trying to get a specific button to trigger a specific event depending on which button was clicked out of the array list. Here was my solution, I tried using .isPressed() first but that always returned false, so I changed it to isArmed() and that worked. Maybe you can try that? My code is written below.
serveButtons was the arrayList that contained all of the different buttons.
orderContentsList was the arrayList that contained the textAreas to be changed.
int which = 0;
for (int i = 0; i < serveButtons.size(); i++) {
if (serveButtons.get(i).isArmed()) {
which = i;
break;
}
}
orderContentsList.get(which).setText(null);
If you need any more information about the arrayLists then let me know.
In my JavaFx application I want to update my BarChart whenever calculate button is clicked. The problem is that I am getting:
java.lang.NullPointerException at
application.StatController.setActivityData(StatController.java:47)
It is always pointing to:`xAxis.setCategories(optionsNames);
But it has elements on the list (See printscreen:https://image.ibb.co/b9YO8Q/Capture.png
In my StatController class I have setActivityData which is called from FormController class.
StatController class:
public class StatController {
#FXML
private BarChart<String, Double> barChart;
#FXML
private CategoryAxis xAxis;
Activities activities = new Activities();
private Map<String, List<Double>> uniqueActivityOptions = new HashMap<>();
private ObservableList<String> optionsNames = FXCollections.observableArrayList();
public StatController(){}
#FXML
private void initialize() {
}
public void setActivityData(Activities activitiesList) {
for(Activity activity : activities.getActivityList()) {
String optionName = activity.getOption();
if(uniqueActivityOptions.containsKey(optionName)) {
uniqueActivityOptions.get(optionName).add((double) activity.getNumber());
} else {
List<Double> activityOptionList = new ArrayList<>();
activityOptionList.add((double) activity.getNumber());
uniqueActivityOptions.put(optionName, activityOptionList);
}
}
for (Map.Entry<String, List<Double>> entry : uniqueActivityOptions.entrySet()) {
optionsNames.add(entry.getKey());
}
xAxis.setCategories(optionsNames);
XYChart.Series<String, Double> series = new XYChart.Series<>();
for (Map.Entry<String, List<Double>> entry : uniqueActivityOptions.entrySet()) {
Double average = calculateAverage(entry.getValue());
series.getData().add(new XYChart.Data<>(entry.getKey().toString(), average));
}
barChart.getData().add(series);
}
private double calculateAverage(List<Double> values) {
double result = 0;
for (Double value : values) {
result += value;
}
return result / values.size();
}
}
FormController class:
public class FormController {
Activities act = new Activities();
List<Activity> activities = act.getActivityList();
private ObservableList<String> opt = FXCollections.observableArrayList(
"Option 1",
"Option 2",
"Option 3"
);
#FXML
private Button calculateButton;
#FXML
private TextField numberField;
#FXML
private ComboBox<String> options;
private String selectedOption;
#FXML
private void initialize() {
options.getItems().addAll(opt);
options.getSelectionModel().selectedItemProperty()
.addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
selectedOption = newValue;
}
});
}
#FXML
public void calculateButtonClicked(){
activities.add(new Activity(selectedOption, Integer.parseInt(numberField.getText())));
StatController sc = new StatController();
sc.setActivityData(act);
}
}
I tested setActivityData method in StatsController and it is working correctly when I am passing Activities.
Please advise what to change in the code to pass and update BarChart.
I know that this is something trivial but I really don't know how to do it.
`
Thank you very much for the help!
Your problem is in FormController#calculateButtonClicked(). You create a new instance of StatController manually and then call the setActivityData() method. This is not how JavaFX works and will result in the xAxis member being null, hence your NullPointerException.
Controller members annotated with the #FXML annotation will be injected by the FXMLLoader class when you call the FXMLLoader#load() method. You will need to use the FXMLLoader class to load the .fxml file that corresponds to the StatController class, which will then create an instance of your StatController object for you and will also inject your xAxis and barChart instances.
Here's a quick (not production ready) example that you will have to adapt for your specific scenario:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(filePath); // your path to the .fxml file
loader.load();
StatController controller = (StatController) loader.getController();
controller.setActivityData(activities); // your activities data
How and when you do that depends on how your scene graph is setup. Looking at your source code, I would suggest the following changes:
MainController.java
public class MainController
implements Initializable {
#FXML
private TabPane tabPane;
#FXML
private Tab formTabPage;
#FXML
private FormController formTabController; // change name to this
#FXML
private Tab statsTabPage;
#FXML
private StatController statsTabController; // change name to this
private MainApp mainApp;
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
#Override // rename your init() method to this
public void initialize(URL location, ResourceBundle resources) {
// add this line
formTabController.setStatController(statTabController);
}
}
FormController.java
public class FormController {
Activities act = new Activities();
List<Activity> activities = act.getActivityList();
private ObservableList<String> opt = FXCollections.observableArrayList(
"Option 1",
"Option 2",
"Option 3"
);
#FXML
private Button calculateButton;
#FXML
private TextField numberField;
#FXML
private ComboBox<String> options;
private String selectedOption;
private StatController statController; // add this member
#FXML
private void initialize() {
options.getItems().addAll(opt);
options.getSelectionModel().selectedItemProperty()
.addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
selectedOption = newValue;
}
});
}
#FXML
public void calculateButtonClicked() {
// change this method here
statController.setActivityData(act);
}
// add this method here
public void setStatController(StatController statController) {
this.statController = statController;
}
}
There are other problems that occur, but this fixes your null pointer exception. The reason this works and your previous code didn't, is because you were manually creating a new instance of StatController and not using the instance that the FXMLLoader had already loaded and mapped to the user interface node for you. All I have done above, is capture a reference to the controller you needed, and provided it to the other through a setter method.
I have StringProperty that consists of two letters (example: 06) that are constantly changing. I have two labels, which I want to bind to each letter of StringProperty, like label1="0" and label2="6". Is there a way to bind label to specific letter of StringProperty?
My code:
#FXML
private Label hoursLabel1;
#FXML
private Label hoursLabel2;
private StringProperty hours;
#FXML
private void initialize() {
hoursLabel1.textProperty().bind(hours);
}
Use Bindings.createStringBinding(...):
#FXML
private void initialize() {
hoursLabel1.textProperty().bind(Bindings.createStringBinding(() ->
hours.get().substring(0,1), hours));
hoursLabel2.textProperty().bind(Bindings.createStringBinding(() ->
hours.get().substring(1,2), hours));
}
This question already has answers here:
Javafx PropertyValueFactory not populating Tableview
(2 answers)
Closed 8 years ago.
I have following basic code in JavaFx. If I want to change the name of PropertyValueFactory("id") to let's say "rid" it does not fill my table anymore. Even if I change the SimpleLongProperty object to rid too. Do you know where the "id" is referencing / pointing to?
public class Main_Controller implements Initializable{
public class Item {
public SimpleLongProperty id = new SimpleLongProperty();
public Long getId() {
return id.get();
}
}
// The table and columns
#FXML TableView<Item> itemTbl;
#FXML TableColumn itemIdCol;
#FXML Button add_Button;
// The table's data
ObservableList<Item> data;
#Override
public void initialize(URL url, ResourceBundle rb) {
// Set up the table data
itemIdCol.setCellValueFactory(
new PropertyValueFactory<Item,Long>("id")
);
data = FXCollections.observableArrayList();
itemTbl.setItems(data);
}
static long nextId = 1;
#FXML
private void handleButtonAction(ActionEvent event) {
Item item = new Item();
item.id.setValue(nextId++);
data.add(item);
}
}
Code With changed PropertyValueFactory:
public class Main_Controller implements Initializable{
public class Item {
public SimpleLongProperty rid = new SimpleLongProperty();
public Long getId() {
return rid.get();
}
}
// The table and columns
#FXML TableView<Item> itemTbl;
#FXML TableColumn itemIdCol;
#FXML Button add_Button;
// The table's data
ObservableList<Item> data;
#Override
public void initialize(URL url, ResourceBundle rb) {
// Set up the table data
itemIdCol.setCellValueFactory(
new PropertyValueFactory<Item,Long>("rid")
);
data = FXCollections.observableArrayList();
itemTbl.setItems(data);
}
static long nextId = 1;
#FXML
private void handleButtonAction(ActionEvent event) {
Item item = new Item();
item.rid.setValue(nextId++);
data.add(item);
}
}
You need a method in your Item class called
public Long getRid(){return rid.get();}
or
public SimpleLongProperty ridProperty(){return rid;}
Note, it's not the name of the variable, which would normally be private, but the name of the getter that matters.
Javadoc link
I have a BorderPane, onto which I placed a MenuBar. At the center of the BorderPane I display differnt AnchorPanes depending on the MenuItem selected. So far so good.
Now, how do I make sure that the Menus change behavior in response to the item selected in the child AnchorPane? So for example if the user selects "Edit", there will be a different action depending on whether the item currently higlighted is a user account, a file etc.
So far I made something along these lines:
The BorderPane controller:
public class MenuTest implements Initializable{
#FXML
private BorderPane borderPaneMain;
#FXML
private AnchorPane anchorPaneMain;
#FXML
private Menu menuEdit;
#FXML
private MenuItem itemEdit;
static String menuMode;
static String entityName;
public MenuTest(){
menuMode ="";
entityName = "";
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
AnchorPane anchor;
try {
anchor = (AnchorPane) new FXMLLoader().load(getClass().getResource("views/MainView.fxml"));
borderPaneMain.setCenter(anchor);
} catch (IOException e) {
e.printStackTrace();
}
}
protected static void setMenuMode(String menuMd, String entityNm){
entityName = entityNm;
menuMode = menuMd;
}
#FXML
private void onEditClick(){
if(entityName.equals(AnchorTest.FILE)){
//Launches correct edit view
new FXMLLoader().load(getClass().getResource("views/EditFile.fxml"));
//Passes the name of the entity so that the controller can retrieve its data
FileEditController.setFile(entityName);
}else if(entityName.equals(AnchorTest.PERSON)){
new FXMLLoader().load(getClass().getResource("views/EditPerson.fxml"));
PersonEditController.setFile(entityName);
}
}
}
The child AnchorPane controller:
public class AnchorTest implements Initializable{
public static final String PERSON = "PERSON";
public static final String FILE = "FILE";
ObservableList<String> peopleList;
ObservableList<String> fileList;
#FXML
private ListView<String> listPeople;
#FXML
private ListView<String> listFiles;
#Override
public void initialize(URL location, ResourceBundle resources) {
peopleList = FXCollections.observableArrayList("Frank","Matin","Anne");
fileList = FXCollections.observableArrayList("hello.txt","holiday.jpg","cv.doc");
listPeople.setItems(peopleList);
listFiles.setItems(fileList);
}
#FXML
private void personSelected(){
MenuTest.setMenuMode(this.PERSON, listPeople.getSelectionModel().getSelectedItem());
}
#FXML
private void fileSelected(){
MenuTest.setMenuMode(this.FILE, listFiles.getSelectionModel().getSelectedItem());
}
}
However I'm not sure that it's the best solution, especially considering the if/elseif statement will need to be altered whenever I add a new element type and its corresponding edit options. So is there any way that I can do this better?
I think if your application has only a few (2-4) different types of "things" that are represented by a AnchorPane, then your approach is totally fine. An alternative to your approach is the state pattern. In that case, your currently selected "item type" would be your state.