How to rerun a program in JavaFX - java

I have 2 controller for 2 fxml files. In one controller I have a handleOpen function which opens a file chooser and gives the path to a Class which I have called model. Then on the other controller a function, treeTableDraw gets this path, after clicking on Draw Button and runs the program. I have Another Button to reset the program. It sets the result back to null, but when open another file to run, the program crashes, because the path is null. How can I reset the program and make it use the new path which is selected from open file chooser?
//Gets the path from model and runs the program
public void treeTableDraw(ActionEvent event) {
new Controller(model.getText());
drawTable();
numberOfFunctions = dc.getFuncAll().size();
numberOfOrganizations = dc.getSortedAssignedOrg().size();
funcLabel.setText(numberOfFunctions + "");
orgLabel.setText(numberOfOrganizations + "");
btnDraw.setDisable(true);
}
/**
* Clrears TreeTableView and sets back labels
*
* #param event
*/
public void treeTableReset(ActionEvent event) {
btnDraw.setDisable(false);
model.setText(null);
funcLabel.setText("0");
orgLabel.setText("0");
treeTable.getColumns().clear();
}
This is RootLayout class which has open file function:
#FXML
private void handleOpen() {
FileChooser fileChooser = new FileChooser();
// Set extension filter
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
"3lgm2 files (*.z3lgm)", "*z3lgm");
fileChooser.getExtensionFilters().add(extFilter);
// Show open file dialog
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
if (file != null) {
path = file.toString();
model.setText(path);
}
}
Here is the model class
public class Model {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text;
}
public final String getText() {
return textProperty().get();
}
public final void setText(String text) {
textProperty().set(text);
}
}
This is the main, where I combine two fxmls and set stage:
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private Model model = new Model();
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("IT-Saturation");
initRootLayout();
showOverView();
}
private void showOverView() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/OverView.fxml"));
loader.setController(new OverViewController(model));
AnchorPane overView = (AnchorPane) loader.load();
rootLayout.setCenter(overView);
} catch (IOException e) {
e.printStackTrace();
}
}
private void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/RootLayout.fxml"));
loader.setController(new RootLayoutController(model));
rootLayout = (BorderPane) loader.load();
// show scene containing the root layout
Scene scene = new Scene(rootLayout);
scene.getStylesheets().add(
getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
// gives controller access to main
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
*
* #return primaryStage
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
public void showMostComputerizedStatistics() {
try {
// Load the fxml file and create a new stage for the popup.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class
.getResource("view/BirthdayStatistics.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Birthday Statistics");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
// Set the persons into the controller.
MostComputerizedController controller = loader.getController();
dialogStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}

The problem was not the path. I had to reset the data which got initialized at the the former run of program. So after setting path to null I just newed the instance of class which had reference to data.
...
public void treeTableReset(ActionEvent event) {
btnDraw.setDisable(false);
//model.setText(null);
funcLabel.setText("0");
orgLabel.setText("0");
treeTable.getColumns().clear();
dc = new DataConstructor();
}

Related

Change scene within the same window

How can I change the scene within the same window, rather than it opening a new window entirely.
Below is where the selectable options are added to a choicebox, with a listener at the end to "observe" when a selection is made, which, when clicked, changes the scene.
private void formulaOption2(){
list2.removeAll(list2);
String a = "Current Ratio";
String b = "Working Capital Ratio";
String c = "Debt to Equity Ratio";
String d = "Gross Profit Margin";
list2.addAll(a,b,c,d);
ChoiceBox2.getItems().addAll(list2);
//A LISTENER TO OBSERVE WHEN USER SELECTS ITEM
ChoiceBox2.getSelectionModel().selectedItemProperty().addListener( (v, oldValue, newValue) -> {
try {
comboSelect2();
} catch (IOException ex) {
Logger.getLogger(Tab1FXMLController.class.getName()).log(Level.SEVERE, null, ex);
}
} );
}
Below is the code that loads the FXML file:
public void comboSelect2() throws IOException {
if("Current Ratio".equals(ChoiceBox2.getSelectionModel().getSelectedItem())){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Tab2FXML.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.setTitle("Current Ratio");
stage.setScene(new Scene(root1));
stage.show();
}
}
Just replace the root of the current scene with the new root you want:
public void comboSelect2() throws IOException {
if("Current Ratio".equals(ChoiceBox2.getSelectionModel().getSelectedItem())){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Tab2FXML.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
ChoiceBox2.getScene().setRoot(root1);
}
}

Communicating with an FXML Controller that's already open

I have searched again and again on this to no avail. I have a JavaFX FXML window which is connected to a Controller; this window is open. Clicking a button on the window triggers the opening of another FXML file, linked to its respective controller.
The second window (optionsUI.fxml and optionsController) has a few radio buttons. When one is clicked, I want the location of an image/button to change in the mainUI window. How do I go about doing that?
mainController:
public void assetPressed(MouseEvent event) {
//Get the source of Handler
HUDButton button = (HUDButton) event.getSource();
//Check if an asset is already selected
//----do a thing
//Open stage
openStage(currentAsset);
} else {
//if the current asset selected and the new asset clicked are the same
//----do something
closeStage();
}
//if the current asset selected and the new asset clicked are different
else {
//----do something else
assetIsSelected = true;
openStage(currentAsset);
}
}
}
//opening optionsUI.fxml
public void openStage(Asset asset) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("optionsUI.fxml"));
Parent root = null;
try {
root = fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
optionsController controller = fxmlLoader.getController();
Scene scene = new Scene(root, 300, 450);
stage.setScene(scene);
if (alreadyExecuted == false) {
stage.initStyle(StageStyle.UNDECORATED);
stage.initOwner(stageControls); //Making the mainUI the owner of the optionsUI
stage.setTitle("HUDEdit Version 3.0.0");
alreadyExecuted = true;
}
The main issue I am having is adding an event handler on the radio buttons which will change a property of the Button that was pressed (currentButton). I searched on this issue, but what I got was what I have already done: to open a new stage with the new values present in the other FXML file.
You can do something like this in your OptionsController (I am going to rename things to conform to standard naming conventions, btw.)
The basic idea here is just to expose a property representing what the user has selected via the radio buttons.
public class OptionsController {
#FXML
private RadioButton radioButton1 ;
#FXML
private RadioButton radioButton2 ;
private SomeType someValue1 = new SomeType();
private SomeType someValue2 = new SomeType();
private final ReadOnlyObjectWrapper<SomeType> selectedThing = new ReadOnlyObjectWrapper<>();
public ReadOnlyObjectProperty<SomeType> selectedThingProperty() {
return selectedThing.getReadOnlyProperty() ;
}
public final SomeType getSelectedThing() {
return selectedThingProperty().get();
}
public void initialize() {
radioButton1.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
selectedThing.set(someValue1);
}
});
radioButton2.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
selectedThing.set(someValue2);
}
});
}
// ...
}
And now when you load Options.fxml you can just observe that property and do whatever you need when it's value changes:
public void openStage(Asset asset) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("optionsUI.fxml"));
Parent root = null;
try {
root = fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
OptionsController controller = fxmlLoader.getController();
controller.selectedThingProperty().addListener((obs, oldSelection, newSelection) -> {
// do whatever you need with newSelection....
});
// etc...
}

JavaFX Returning Correct Data From One Controller to Another

I have two controllers. One controller manages most of the main functionality, the other controls a simple pop up prompt, accessed from the main controller.
This is the function stored in the main controller, used to access the prompt.
public void deletePrompt(){
DeletePromptController controller = new DeletePromptController();
boolean result = controller.showPrompt("/MainWindow//DeletePrompt.fxml");
if(result){
System.out.println("Deleted");
}else{
System.out.println("Canceled");
}
}
This is the prompt controller
public class DeletePromptController extends ShowWindow {
public Label question;
public Button delete, cancel;
private boolean result = true;
boolean showPrompt(String path){
showWindow(path);
return result;
}
public void delete(){
System.out.println("D");
result = true;
Stage stage = (Stage) delete.getScene().getWindow();
stage.close();
}
public void cancel(){
System.out.println("C");
result = false;
Stage stage = (Stage) cancel.getScene().getWindow();
stage.close();
}
}
And this is the block used to load and show the delete prompt fxml file.
public class ShowWindow {
public void showWindow(String path){
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(path));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(new Scene(root));
stage.showAndWait();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
Everything is working except one thing. The main controller when getting the result from the prompt controller is not getting the correct Boolean result.
Output when delete is pressed:
D
Canceled
Output when cancel is pressed:
C
Canceled
D should be followed by Deleted.
Anything helps.
FXMLLoader creates a new controller instance, since the fx:controller attribute is provided in the fxml.
You've basically got 2 options:
Remove the fx:controller attribute from the fxml and specify the controller yourself:
public void showWindow(String path){
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(path));
fxmlLoader.setController(this);
Parent root = fxmlLoader.load();
or
Get the controller created by the FXMLLoader
public static <T> T showWindow(String path){
try {
FXMLLoader fxmlLoader = new FXMLLoader(ShowWindow.class.getResource(path));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(new Scene(root));
stage.showAndWait();
return fxmlLoader.getController();
}catch(IOException ex){
ex.printStackTrace();
}
return null;
}
boolean showPrompt(String path) {
return ShowWindow.<DeletePromptController>showWindow(path).result;
}

How to reset a selected path from file chooser in JavaFx

I have a reset and Draw button on a slide panel. I choose a desired file from file chooser, which is in RootLayout class, and pass the file path to a controller class. Then it does some processes and initializes field in DataCunstructor class. By clicking on Draw a TreeTableView will be shown on slide pane, which is in MainController class. When I click my reset button the table will be cleared but I do not know how to reset the chosen path. After reseting if I click Draw again the same treetable comes up. and If I choose another file and hit Draw, the program breaks.
How can I reset all fields including the path to null, and be able to choose another file and process that one?
Here is my Draw and Reset in MainController class:
public void treeTableDraw(ActionEvent event) {
drawTable();//creates the TreeTableView
numberOfFunctions= dc.getFuncAll().size();
numberOfOrganizations = dc.getSortedAssignedOrg().size();
funcLabel.setText(numberOfFunctions+"");//set Lable value
orgLabel.setText(numberOfOrganizations + "");//set Lable value
}
public void treeTableReset(ActionEvent event){
funcLabel.setText("0");//reset Label
orgLabel.setText("0");
treeTable.getColumns().clear(); //clears columns (TreeTable)
///////////////////////////////////////
//non of the following did the path reset//
///////////////////////////////////////
//dc = new DataConstructor();
//Controller controller = new Controller();
//controller.setPath(null);
RootLayoutController rlc = loader.getController();
rlc.reset();
}
My File Chooser in RootLayout class:
#FXML
private void handleOpen() {
FileChooser fileChooser = new FileChooser();
// Set extension filter
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
"3lgm2 files (*.z3lgm)", "*z3lgm");
fileChooser.getExtensionFilters().add(extFilter);
// Show save file dialog
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
path = file.toString();
if (path != null) {
new Controller(path);
}
}
public void reset(){
path = null;
}
I add OverView at the center of rootlayout here at main class:
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
//private ObservableList<DataConstructor> treeTableData = FXCollections.observableArrayList();
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("IT-Saturation");
initRootLayout();
showOverView();
}
private void showOverView() {
try{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/OverView.fxml"));
AnchorPane overView = (AnchorPane) loader.load();
rootLayout.setCenter(overView);
}catch(IOException e){
e.printStackTrace();
}
}
private void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
//show scene containing the root layout
Scene scene = new Scene(rootLayout);
scene.getStylesheets().add(
getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
//gives controller access to main app
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
File file = getFilePath();
if (file != null) {
loadDataFromFile(file);
}
}
/**
* Returns the main stage.
* #return primaryStage
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
Just declare a reset() in your RootLayout class:
public class RootLayout {
private Path path;
#FXML
private void handleOpen() {
...
path = file.toString();
}
public void reset() {
path= null;
}
}
Never construct the constructor using the keyword new, always get it from the FXMLLoader.
public class MainController {
...
RootLayoutController controller = loader.getController();
controller.reset();
...
}

JavaFX open new scene with FXML

So I've been trying to do this for atleast 4 hours now and with no succes.
The case: I need to open a new FXML Window after pressing a button on my Controller class.
I'm using JavaFX for this.
We are working in packages like this.
lobby.gui, login.gui etc...
It doesn't give an error message but the Scene will not start.
This is the LoginFXController where the button is pressed.
public class LoginFXController implements Initializable
{
DatabaseMediator mediator;
//INLOGGUI FXML
#FXML TextField tf_inlogusername;
#FXML PasswordField pf_inlogpassword;
#FXML Button btn_inlog;
#FXML Button btn_register;
#Override
public void initialize(URL url, ResourceBundle rb)
{
mediator = new DatabaseMediator();
}
public void loginPersoon(Event event)
{
String gebruikersnaam = tf_inlogusername.getText();
String wachtwoord = pf_inlogpassword.getText();
Persoon p = new Persoon(gebruikersnaam, wachtwoord);
Boolean check = mediator.controleerPersoonsGegevens(gebruikersnaam, wachtwoord);
if(check == false)
{
showDialog("Error", "Gegevens komen al voor in het Systeem!");
}
else
{
showDialog("Succes", "Welkom: " + gebruikersnaam);
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("lobby.gui/LobbyGUI.fxml"));
LobbyGUI controller = new LobbyGUI();
loader.setController(controller);
loader.setRoot(controller);
Parent root = (Parent)loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
}
catch(IOException e)
{
showDialog("Error", e.getMessage());
}
}
}
And I'm trying to fire of this new class
public class LobbyGUI extends Application
{
#Override
public void start(Stage stage) throws IOException
{
Parent root = FXMLLoader.load(getClass().getResource("LobbyGUI.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}

Categories

Resources