I am still very new to Java and have been trying to figure out how to enable a text area for editing if a radio button is selected for a while now. I have been googling and reading posts on various forums, however i don;t understand what they are doing or how to do it within my program what so ever.
Here is what I have so far:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package labscheduler;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.*;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* #author S02105032
*/
public class FXMLLabSchedulerDocController implements Initializable {
#FXML
private TextField txtRequestorName;
#FXML
private TextField txtRequestorEmail;
#FXML
private TextField txtEventTitle;
#FXML
private TextField txtNumParticipants;
#FXML
private TextField txtEventDate;
#FXML
private TextField txtStartTime;
#FXML
private TextField txtEndTime;
#FXML
private ToggleButton togStartTime;
#FXML
private ToggleButton togEndTime;
#FXML
private CheckBox chkPrinter;
#FXML
private RadioButton rbYes;
#FXML
private RadioButton rbNo;
#FXML
private TextArea txtareaMessage;
private String requestorName;
private String requestorEmail;
private String eventTitle;
private int participants = 0;
private Date eventDate;
private Date startTime;
private Date endTime;
private String printer;
private String message;
#FXML
private void handleBtnSubmit(ActionEvent event) {
requestorName = txtRequestorName.getText();
requestorEmail = txtRequestorEmail.getText();
eventTitle = txtEventTitle.getText();
participants = Integer.parseInt(txtNumParticipants.getText());
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/YY");
try {
eventDate = sdf.parse(txtEventDate.getText());
} catch (ParseException ex) {
System.out.println("invalid date format");
}
SimpleDateFormat stdf = new SimpleDateFormat("hh:mm");
try {
startTime = stdf.parse(txtStartTime.getText());
} catch (ParseException ex) {
System.out.println("invalid start time format");
}
SimpleDateFormat etdf = new SimpleDateFormat("hh:mm");
try {
endTime = etdf.parse(txtEndTime.getText());
} catch (ParseException ex) {
System.out.println("invalid end time format");
}
if(chkPrinter.isSelected()) {
printer = "printer requested";
}
else {
printer = "no printer needed";
}
if(rbYes.isSelected() && !rbNo.isSelected()) {
txtareaMessage.setEditable(true);
message = txtareaMessage.getText();
}
else {
txtareaMessage.setEditable(false);
message = "None";
}
}
#FXML
private void handleButtonClose(ActionEvent event) {
System.out.println("Application Close!");
Platform.exit();
}
#FXML
private void handleButtonClear(ActionEvent e) {
System.out.println("Clear All Fields!");
txtRequestorName.setText("");
txtRequestorEmail.setText("");
txtEventTitle.setText("");
txtNumParticipants.setText("");
txtEventDate.setText("");
txtStartTime.setText("");
txtEndTime.setText("");
chkPrinter.setSelected(false);
rbYes.setSelected(false);
rbNo.setSelected(false);
txtareaMessage.setText("");
}
// Radio Buttons need to be set to group so only one can be selected at a time
// If Radio Btn Yes is checked, enable txt area message, else disable
// Set Toggle Buttons to toggle between AM & PM
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
When I select either of the radio buttons, it does not seem to be making the text area editable.
The state of JavaFX controls is represented by observable properties. So the RadioButton has a selectedProperty and the TextArea has a editableProperty. You can set and retrieve the values of these with the usual set/get (or set/is) methods: txtareaMessage.setEditable(rbYes.isSelected()), you can also observe them for changes:
rbYes.selectedProperty().addListener(...);
or you can bind the value of one property to the value of another. Binding essentially just registers a listener with one property and updates the other property when the observed property changes.
In your case the logic is very simple (the value of the text area's editable property should be the same as the value of the radio button's selected property), so all you need is to establish a simple binding in the initialize() method:
txtareaMessage.editableProperty().bind(rbYes.selectedProperty());
if(rbYes.isSelected() && !rbNo.isSelected()) {
txtareaMessage.setEditable(true);
message = txtareaMessage.getText();
}
else {
txtareaMessage.setEditable(false);
message = "None";
}
That segment of code is within an ActionListener for your button (handleBtnSubmit), therefore from what I understand, you need an ActionListener on your radio buttons to fire the code aforementioned.
Create an ToggleGroup like this.
final ToggleGroup group = new ToggleGroup();
Add the Radiobuttons to the "group".
RadioButton yes = new RadioButton("yes");
yes.setToggleGroup(group);
RadioButton no= new RadioButton("no");
no.setToggleGroup(group);
Check if the "yes" RadioButton is selected.
yes.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
if(yes.isSelected()){
textField.setEnabled(true);
}else{
textField.setEnabled(false);
}
}
});
Related
I'm currently working on a password manager. Before making any changes to a certain service, the program will ask the user for a password for authorization and then proceed to show the appropriate dialog, if the password is correct.
The issue that I'm having is that if I go through the cycle of putting in my password to make the change, click "ok", and then proceeding to make changes on the shown dialog, on the next turn if instead of putting the password when prompted I close the prompt, then the program retrieves the password from the previous iteration although it has been explicitly cleared. Resulting in the concurrent dialog showing, which is only supposed to show if you put in the correct password.
private void handleEditButton(MouseEvent event) {
Optional<String> rslt = passwordConfirmDialog.showAndWait();
if (rslt.get().equals(""))
return; //Do not proceed
String userInput = rslt.get().trim();
// Complex expression, but use of && statement is necessary to avoid an
// unecessary call to db and have return statement on this IF
if (!(!userInput.isBlank() && isCorrectPassword(userInput))) {
// show dialog
AlertConfigs.invalidPasswordTransactionFailed.showAndWait();
return;
}
System.out.println("Edit Handler: Correct password. -> " + userInput);
//Proceed to show next dialog...
private void initializePasswordConfirmDialog() {
passwordConfirmDialog.setTitle("User Account Control");
passwordConfirmDialog.setHeaderText("Please enter your password to continue.");
// Set the button types.
ButtonType ok = new ButtonType("Ok", ButtonData.OK_DONE);
passwordConfirmDialog.getDialogPane().getButtonTypes().addAll(ok, ButtonType.CANCEL);
final PasswordField psField = new PasswordField();
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
grid.add(new Label("Please Enter your password"), 0, 0);
grid.add(psField, 1, 0);
passwordConfirmDialog.getDialogPane().setContent(grid);
passwordConfirmDialog.setResultConverter(buttonType -> {
String rslt = "";
if (buttonType == ok) {
rslt = psField.getText();
}
psField.clear();
return rslt;
});
}
I've posted a video on YouTube to help visualize the problem. https://youtu.be/sgayh7Q7Ne8
The PasswordField in initializePasswordConfirmDialog() is cleared because whenever I run the the prompt the second time, the PasswordField is blank (visually). Nevertheless, for some reason it still grabs the result from the previous iteration.
The initializePasswordConfirmDialog() is called once inside the constructor and is responsible for set the passwordConfirmDialog variable with the adequate properties.
Some additional code:
HomeController.java
#FXML
private GridPane servicesGrid;
private Dialog<String> passwordConfirmDialog;
private Dialog<Service> editServiceDialog;
private final int NUM_COLUMNS = 7;
public HomeController() {
passwordConfirmDialog = new Dialog<>();
initializePasswordConfirmDialog();
editServiceDialog = new Dialog<>();
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
loadServicesGridpane();
}
private void loadServicesGridpane() {
ArrayList<Service> currS = acct.getServices();
// int currentRow = 1;
for (Service s : currS)
addRowToServiceGrid(s);
}
private void addRowToServiceGrid(Service s) {
int rowIdx = servicesGrid.getChildren().size() / 4;
Button editButton = new Button("Edit");
editButton.setOnMouseClicked(event -> {
handleEditButton(event);
});
Button deleteButton = new Button("Delete");
deleteButton.setOnMouseClicked(event -> {
handleDeleteButton(event);
});
deleteButton.setId(s.getServiceName());
Label currServiceName = new Label(s.getServiceName());
currServiceName.setId(s.getServiceName());
Label currUsername = new Label(s.getServiceUsername());
Label currPassword = new Label(s.getServicePassword());
Label dateCreated = new Label(s.getDateCreated());
Label lastPssdChange = new Label(s.getLastPasswordChange());
servicesGrid.addRow(rowIdx, currServiceName, currUsername, currPassword, dateCreated, lastPssdChange,
deleteButton, editButton);
}
To study the problem in isolation, I refactored this example to permit reusing the dialog. As shown below, reusing the dialog requires clearing the password field. Replace the parameter dialog with an invocation of createDialog() to see that creating the dialog each time does not require clearing the password field. Comparing the profile of each approach may help you decide which approach is acceptable; in my experiments, reuse added negligible memory overhead (~250 KB), and it protracted garbage collection slightly(~50 ms).
#!/bin/sh
java … DialogTest -reuse &
pid1=$!
java … DialogTest -no-reuse &
pid2=$!
echo $pid1 $pid2
jconsole $pid1 $pid2
Unfortunately, creating the dialog each time may only appear to solve the problem; it may have exposed a latent synchronization problem. In particular, verify that your result converter's callback executes on the JavaFX Application Thread. To illustrate, I've added a call to Platform.isFxApplicationThread() in resultsNotPresent() below.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* #see https://stackoverflow.com/q/73328282/230513
* #see https://stackoverflow.com/a/44172143/230513
*/
public class DialogTest extends Application {
private static boolean REUSE_DIALOG = true;
private record Results(String text, String pass) {
private static Results of(String text, String pass) {
return new Results(text, pass);
}
}
#Override
public void start(Stage stage) {
var label = new Label("Reuse: " + REUSE_DIALOG);
var button = new Button("Button");
if (REUSE_DIALOG) {
var dialog = createDialog();
button.setOnAction(e -> showDialog(dialog));
} else {
button.setOnAction(e -> showDialog(createDialog()));
}
stage.setScene(new Scene(new HBox(8, label, button)));
stage.show();
}
private Dialog<Results> createDialog() {
var dialog = new Dialog<Results>();
dialog.setTitle("Dialog Test");
dialog.setHeaderText("Please authenticate…");
var dialogPane = dialog.getDialogPane();
dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
var text = new TextField("Name");
var pass = new PasswordField();
dialogPane.setContent(new VBox(8, text, pass));
dialog.showingProperty().addListener((o, wasShowing, isShowing) -> {
if (isShowing) {
Platform.runLater(pass::requestFocus);
}
});
dialog.setResultConverter((ButtonType bt) -> {
if (ButtonType.OK == bt) {
var results = Results.of(text.getText(), pass.getText());
pass.clear();
return results;
}
pass.clear();
return null;
});
return dialog;
}
private void showDialog(Dialog<Results> dialog) {
var optionalResult = dialog.showAndWait();
optionalResult.ifPresentOrElse(
(var results) -> System.out.println(results),
(this::resultsNotPresent));
}
private void resultsNotPresent() {
System.out.println("Canceled on FX application thread: "
+ Platform.isFxApplicationThread());
}
public static void main(String[] args) {
if (args.length > 0) {
REUSE_DIALOG = args[0].startsWith("-r");
}
launch(args);
}
}
Can someone tell me why there is a delay on Checkbox initialization with my Code?
What happens is that if I open the program, I have to click the Checkbox several times until it performes the desired Action.
The Controller also contains setter and getter methods.
Thanks a lot
public class Controller {
/* Defined variables */
#FXML
private CheckBox happyboxtick;
#FXML
private VBox topbox;
#FXML
private VBox designbox;
#FXML
public void initialize(){
happyboxtick.setSelected(true);
designbox.setVisible(false);
designbox.getChildren().removeAll();
topbox.setVisible(true);
topbox.getChildren().addAll();
}
#FXML
public void doSomething(ActionEvent e) {
//final CheckBox chk1 = new CheckBox("chk 1");
//final CheckBox chk2 = new CheckBox("chk 2");
EventHandler eh = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (event.getSource() instanceof CheckBox) {
CheckBox chk = (CheckBox) event.getSource();
//System.out.println("Action performed on checkbox " + chk.getText());
//System.out.println(chk);
if(chk.isSelected()){
System.out.println("My box is selected.");
topbox.setVisible(false);
topbox.getChildren().removeAll();
designbox.setVisible(true);
designbox.getChildren().addAll();
} else
{
System.out.println("My box is not selected.");
topbox.setVisible(true);
topbox.getChildren().addAll();
designbox.setVisible(false);
designbox.getChildren().removeAll();
}/*
if ("Yes".equals(chk.getText())) {
chk2.setSelected(!chk1.isSelected());
} else if ("chk 2".equals(chk.getText())) {
chk1.setSelected(!chk2.isSelected());
}*/
}
}
};
happyboxtick.setOnAction(eh);
//chk1.setOnAction(eh);
//chk2.setOnAction(eh);
}
}
The Code compiles perfectly.
Initialization works.
The right Option is selected.
But when I click the box, I may have to click several times until the Elements are shown. And I don't know why.
I am using JavaFX Netbeans and Scene Builder for my program. I am trying to create a student information input scene. I have all of the inputs working and going to a text file right now. It also displays a Success pop up box. However, I am trying to make it so that if one of the inputs is blank, nothing will be inputted and an error popup will come up. Right now both popups work, but it is broken and only the success comes up. No matter if all inputs are there or not, the error box will come up 4 times. I cannot figure out why because I have each if statement there. I also don't know where to start with not inputting any information if one field is not filled out.
import javafx.collections.*;
import javafx.event.ActionEvent;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.io.*;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.StandardOpenOption;
import java.util.ResourceBundle;
public class CController implements Initializable {
#FXML
private Button button;
#FXML
private Text Student;
#FXML
private Button Add;
#FXML
private ComboBox Grade;
#FXML
private ComboBox Type;
#FXML
private TextField Name;
#FXML
private TextField ID;
ObservableList<String> GRADES = FXCollections.observableArrayList("9", "10", "11", "12");
ObservableList<String> EVENTS = FXCollections.observableArrayList("Business Law and Ethics", "Buying and Merchandising", "Financial Services", "Hospitality Services", "Marketing Communications", "Sports and Entertainment Marketing", "Travel and Tourism", "Accounting Applications", "Apparel and Accessories Marketing", "Automotive Services Marketing", "Business Finance", "Business Services Marketing", "Food Marketing", "Hotel and Lodging Management", "Human Resources Management", "Marketing Management", "Quick Serve Restaurant Management", "Restaurant and Food Service Management", "Retail Merchandising", "Sports and Entertainment Marketing");
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Parent FXMLDocument2Parent = FXMLLoader.load(getClass().getResource("B.fxml"));
Scene FXMLDocument2Scene = new Scene(FXMLDocument2Parent);
Stage AppStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
AppStage.setScene(FXMLDocument2Scene);
AppStage.show();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
Grade.setItems(GRADES);
Type.setItems(EVENTS);
}
#FXML
public void addtolist(ActionEvent e) throws IOException {
Alert success = new Alert(Alert.AlertType.INFORMATION);
success.setTitle("Information");
success.setHeaderText(null);
success.setContentText("Student Added");
success.showAndWait();
Alert nosave = new Alert(Alert.AlertType.INFORMATION);
String idinput = ID.getText();
SendToText("\r\n");
SendToText(idinput);
if (idinput.isEmpty())
nosave.setTitle("Error");
nosave.setHeaderText(null);
nosave.setContentText("Please Enter All Student Information");
nosave.showAndWait();
String nameinput = Name.getText();
SendToText(",");
SendToText(nameinput);
if (nameinput.isEmpty())
nosave.setTitle("Error");
nosave.setHeaderText(null);
nosave.setContentText("Please Enter All Student Information");
nosave.showAndWait();
String grade;
grade = (String) Grade.getValue();
SendToText(",");
SendToText(grade);
if (grade.isEmpty())
nosave.setTitle("Error");
nosave.setHeaderText(null);
nosave.setContentText("Please Enter All Student Information");
nosave.showAndWait();
String event;
event = (String) Type.getValue();
SendToText(",");
SendToText(event);
if (event.isEmpty())
nosave.setTitle("Error");
nosave.setHeaderText(null);
nosave.setContentText("Please Enter All Student Information");
nosave.showAndWait();
}
private void SendToText(String cartone) throws IOException {
Path file = Paths.get("C:/Users/Shaheer.K/Documents/Shaheer/IAiffy/src/ia/Extra/list.txt");
byte[] data = cartone.getBytes();
OutputStream output = null;
try {
output = new
BufferedOutputStream(Files.newOutputStream(file, StandardOpenOption.APPEND));
output.write(data);
output.flush();
output.close();
} catch (IOException e) {
System.out.println("Message: " + e);
}
}
}
I am creating an application where I'm combining FXML and regular javaFX to create an application. I'm, however, experiencing problems writing EventHandlers for a Stage-subclass called AddItemWindow that generates custom windows.
The application shows a list of items (keys and weapons) in an inventory. The user can add items, and needs to press a button to add the item of his choice (Add Key or Add Weapon).
A new window then pops up, where the user has to input the relevant data. It will generate a GridPane with the TextFields where the user can input the data. This will be a custom GridPane, depending on the ItemType. It will then load the FXML and add the GridPane.
With the below code, I am getting LoadExceptions for my SetOnAction-code for the buttons cancelling the window or confirming the new item.
Would any-one know where I'm making an error?
/* StartUp Class*/
package main;
//imports from javafx and java
import domain.DomainController;
import gui.OverviewWindow;
public class StartUpGUI extends Application {
#Override
public void start(Stage primaryStage) {
Parent root = new OverviewWindow(new DomainController());
Scene scene = new Scene(root);
primaryStage.setTitle("Weapons and Keys");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String... args) {
Application.launch(StartUpGUI.class, args);
}
}
/* OverviewWindow, subclass of BorderPane */
package gui;
//imports from javafx and java
import domain.DomainController;
import domain.ItemType;
public class OverviewWindow extends BorderPane{
#FXML
private Button btnAddWeapon;
#FXML
private Button btnAddKey;
#FXML
private TextArea txaOverview;
private DomainController dc;
this.dc = dc;
FXMLLoader loader = new FXMLLoader(getClass().getResource("OverviewWindow.fxml"));
loader.setRoot(this);
loader.setController(this);
try{
loader.load();
txaOverview.setText(dc.showOverview()); // showOverview returns a String containing a toString of all items in the inventory
}
catch (IOException ex){
throw new RuntimeException(ex);
}
}
#FXML
public void btnAddWeaponOnAction(ActionEvent event){
try{
add(ItemType.WEAPON); // ItemType is an Enum where all the properties of the items are defined; for Weapon: name, weight, level, power, used(boolean)
}
catch (Exception e){
throw e;
}
}
#FXML
public void btnAddKeyOnAction(ActionEvent event){
try{
add(ItemType.SLEUTEL); // ItemType is an Enum where all the properties of the items are defined; for Key: name, weight, level, door
}
catch (Exception e){
throw e;
}
}
private void add(ItemType itemType){
Stage stage = new Stage();
stage.setTitle(itemType== VoorwerpSoort.WEAPON ? "Add Weapon" : "Add Key");
AddItem addItem = new AddItem(dc,itemType,this);
addItem.setOnHiding(new EventHandler<WindowEvent>(){
#Override
public void handle(WindowEvent e){
txaOverview.setText(dc.showOverview()); // when we close the AddItemWindow, we will update the item overview by having the domain controller get this data from the repository
}
});
addItem.show();
}
}
/* AddItemWindow, a subclass of Stage*/
package gui;
// import relevant javafx and java classes
import domain.DomainController;
import domain.ItemType;
public class AddItemWindow extends Stage {
#FXML
private BorderPane addRoot;
#FXML
private Button btnOK;
#FXML
private Button btnCancel;
private DomainController dc;
private ItemType itemType;
private Parent parent;
private TextField[] txfAttributes;
public AddItemWindow(DomainController dc, ItemType itemType, OverviewWindow overviewWindow){
this.dc = dc;
this.itemType = itemType;
this.parent = overviewWindow;
this.setScene(buildGUI(dc,itemType,overviewWindow));
}
private Scene buildGUI(DomeinController dc, VoorwerpSoort vwps, OverzichtSchermController ovsController){
Parent root = new BorderPane();
GridPane properties = new GridPane();
properties.setPadding(new Insets(10));
properties.setHgap(10);
properties.setVgap(10);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHalignment(HPos.RIGHT);
ColumnConstraints col2 = new ColumnConstraints();
properties.getColumnConstraints().addAll(col1, col2);
String[] attributes = itemType.attributeNames();
txfAttributes = new TextField[attributes.length];
for(int i = 0; i<attributes.length; i++){
properties.add(new Label(attributes[i]),0,i);
properties.add(txfAttributes[i] = new TextField(),1,i);
}
((BorderPane) root).setCenter(properties);
FXMLLoader loader = new FXMLLoader(getClass().getResource("AddItemWindow.fxml"));
loader.setRoot(root);
loader.setController(root);
try{
loader.load();
return new Scene(root);
}
catch(IOException e){
throw new RuntimeException(e);
}
}
// NOT WORKING
#FXML
public void btnOKOnAction(){
addItem();
}
// NOT WORKING
#FXML
public void btnCancelOnAction(ActionEvent event){
hide();
}
private void voorwerpToevoegen(){ // we're calling the domaincontroller to add the new item to the repository
switch (itemType)
{
// for the item, add an item by getting the value of each TextField, which are the
// parameters for a constructor of the new item
case WEAPON:
dc.addWeapon(txfAttributes[0].getText(),
Double.parseDouble(txfAttributes[1].getText()),
Integer.parseInt(txfAttributes[2].getText()),
Integer.parseInt(txfAttributes[3].getText()),
Boolean.parseBoolean(txfAttributes[4].getText()));
break;
case KEY:
dc.addKey(txfAttributes[0].getText(),
Double.parseDouble(txfAttributes[1].getText()),
Integer.parseInt(txfAttributes[2].getText()),
Integer.parseInt(txfAttributes[3].getText()));
break;
}
hide();
}
}
At the top you have #FXML private Button btnOK; which is good.
To specify the button's action in Java code, you can use this Java 8 syntax in your buildGUI() method (see JavaFX 8 Event Handling Examples):
btnOK.setOnAction((event) -> addItem());
If you're not using Java 8, see UI Control Sample.
You don't need the methods annotated with #FXML.
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.