How to close pop up windows in javafx? - java

I have two scenes - login prompt and Main screen. The openLoginPrompt() function opens the login prompt. Then I call the handleLogin() function which tries to authenticate a user. When login is successful I would like to close the login prompt and return to the Main screen. However if I don't set primaryStage as static primaryStage seems to be null when the handleLogin() function is called. Why does this happen and is there a better alternative to close the stage?
/*
* 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 chatapplication;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
/**
*
* #author babaji
*/
public class Controller {
private static Stage primaryStage;
#FXML
private Button openLoginPrompt;
#FXML
private Button login;
#FXML
private TextField username;
#FXML
private PasswordField password;
#FXML
private Label loginMessage;
#FXML
private AnchorPane loginPrompt;
#FXML
private void openLoginPrompt() {
try {
primaryStage = new Stage();
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ChatApplication.class.getResource("LoginPrompt.fxml"));
AnchorPane rootLayout = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
private void handleLogin() {
Database dbObj = new Database();
Connection conn = dbObj.connectToDb("chat");
String uname = username.getText();
String psswd = password.getText();
ResultSet rs = null;
try {
String sql = "SELECT * FROM user WHERE user_name=? AND password=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, uname);
ps.setString(2, psswd);
rs = ps.executeQuery();
}
catch(SQLException e) {
e.printStackTrace();
}
int count = 0;
try {
if(rs != null) while(rs.next()) count++;
}
catch(SQLException e) {
count = 0;
}
if(count == 1) {
System.out.println("Successfully Logged in");
/*This is where the problem Lies. If I dont't set primaryStage as
static, primaryStage returns null. Why does this happen and is there
some other way to close the window?s
*/
if(primaryStage != null) primaryStage.close();
}
else {
System.out.println("Failed to login.");
loginMessage.setText("Incorrect username or password");
}
}
}

You have two controller instances, one for LoginPrompt.fxml and one for another FXML you haven't shown (let's call it the "main" fxml). openLoginPrompt is called on the "main" instance, and initializes primaryStage, and loads LoginPrompt.fxml. When you load the FXML, the FXMLLoader creates a new instance of the controller, which doesn't have primaryStage initialized (assuming it's not static); so when handleLogin() is invoked on the LoginPrompt.fxml controller, it is null.
It's a really bad idea to use the same controller class for two different FXML files, as it leads to all sorts of confusing scenarios such as this, where different fields are initialized in different instances of the class. You should use a different controller class for each FXML file.
In this case, you could define a LoginController class. Edit LoginPrompt.fxml to use this controller class instead. You can expose various properties from that class and observe them from the main controller when you open the login window:
public class LoginController {
#FXML
private Label loginMessage ;
private final BooleanProperty loggedIn = new SimpleBooleanProperty();
public BooleanProperty loggedInProperty() {
return loggedIn ;
}
public final boolean isLoggedIn() {
return loggedInProperty().get();
}
public final void setLoggedIn(boolean loggedIn) {
loggedInProperty().set(loggedIn);
}
#FXML
private void handleLogin() {
// existing code you had in the previous version...
if (count == 1) {
System.out.println("Successfully logged in");
setLoggedIn(true);
} else {
System.out.println("Failed to login.");
loginMessage.setText("Incorrect username or password");
}
}
}
And then in your main controller you do
#FXML
private void openLoginPrompt() {
try {
Stage loginStage = new Stage();
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ChatApplication.class.getResource("LoginPrompt.fxml"));
AnchorPane rootLayout = (AnchorPane) loader.load();
LoginController loginController = loader.getController();
loginController.loggedInProperty().addListener((obs, wasLoggedIn, isNowLoggedIn) -> {
if (isNowLoggedIn) {
loginStage.hide();
}
});
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
loginStage.setScene(scene);
loginStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
There is no need to make the Stage a field with this version.
I should also mention there's a "quick and dirty" way to close the stage directly from the LoginController:
loginMessage.getScene().getWindow().hide();
which would avoid needing the property and even getting a reference to the LoginController from the main controller. However, you often have situations where you may need data from one controller in another, and the first technique is a more generally useful approach.

Related

JavaFX error "Application launch must not be called more than once" while running 2 Test cases

I am using JavaFX to write a sample video player. But the tests fails when run together, ( Note: individually test passes).
Error: Unexpected exception thrown: java.lang.IllegalStateException: Application launch must not be called more than once
I understand that calling launch() twice on same Application Instance is causing this issue as per this . But I am not able to understand, that after one test completes, why the app is still running ? Why new instance is not getting created for 2nd test. testUnsupportedVideoFileThrowsError() succeeds but testSupportedVideoFilePlaysSuccessfully() fails.
package media;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import java.io.File;
public class PlayVideoSnippet extends Application {
private static String source;
private Media media = null;
private MediaPlayer mediaPlayer = null;
private MediaView mediaView = null;
private Scene scene = null;
public static void playVideo(String source) {
PlayVideoSnippet.source = source;
PlayVideoSnippet.launch();
}
#Override
public void start(Stage stage) throws InterruptedException {
try {
media = new Media(new File(source).toURI().toString());
//onError close the app
media.setOnError(() -> {
Platform.exit();
});
//Create MediaPlayer, with media
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
//onEnd of media, close the app
mediaPlayer.setOnEndOfMedia(() -> {
Platform.exit();
});
//Create media viewer
mediaView = new MediaView(mediaPlayer);
//create scene
scene = new Scene(new Group(), media.getWidth(), media.getHeight());
stage.setScene(scene);
stage.setTitle("Video Player");
//attach the mediaView to the scene root
((Group) scene.getRoot()).getChildren().add(mediaView);
stage.show();
} finally {
System.out.println("Inside finally");
stage.close();
}
}
}
package media;
import javafx.scene.media.MediaException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PlayVideoSnippetTest {
/**
* Tests for {#link PlayVideoSnippet#playVideo(String)}.
*/
final String PATH_OF_SUPPORTED_VIDEO_FILE = "src/test/resources/file_example_MP4_480_1_5MG.mp4";
final String PATH_OF_UNSUPPORTED_VIDEO_FILE = "src/test/resources/file_example_WMV_480_1_2MB.wmv";
#Test
void testSupportedVideoFilePlaysSuccessfully() {
assertDoesNotThrow(() -> PlayVideoSnippet.playVideo(PATH_OF_SUPPORTED_VIDEO_FILE));
}
#Test
void testUnsupportedVideoFileThrowsError() {
RuntimeException exception = assertThrows(RuntimeException.class, () -> PlayVideoSnippet.playVideo(PATH_OF_UNSUPPORTED_VIDEO_FILE));
assertTrue(exception.getCause().getClass().equals(MediaException.class));
}
}
I was able to fix the issue with help of below inputs:
Using TestFX for testing purpose as suggested by #jewelsea.
Inputs from #James_D
StackOver flow issue
ApplicationTest.launch() method internally takes care of setting up primary stage and cleaning before each test.
Solution:
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
class VideoTest extends ApplicationTest {
final String pathOfSupportedFile = "video.mp4";
final String pathOfUnsupportedFile = "video.wmv";
#Test
void testSupportedVideoFilePlaysSuccessfully() throws Exception {
assertDoesNotThrow(() -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
new String[]{pathOfSupportedFile}));
}
#Test
void testUnsupportedVideoFileThrowsError() throws Exception {
RuntimeException exception = assertThrows(RuntimeException.class,
() -> PlayVideoSnippetTest.launch(PlayVideoSnippet.class,
new String[]{pathOfUnsupportedFile}));
assertTrue(exception.getCause().getCause().getClass().equals(MediaException.class));
}
}

Exception handling in static initializer

Normally I handle my exceptions by showing some custom Alert (JavaFX) with details, but JavaFX runtime is not initialized at all when the static initializer of my class runs.
Is there any way to handle such exception without printing its content to output like an animal?
public class MyStaticInitializedClass {
static {
try {
//do the things that may throw exception
} catch(Exception ex) {
ExceptionHandler.showException(ex);
}
}
}
public class ExceptionHandler {
public static void showException(Exception ex) {
//constructs JavaFX alert with exception details
alert.show();
}
}
First consder if you shouldn't let the application simply crash and log the reason. A failure in a static initializer typically means there's something seriously wrong with the environment, which is not likely something you can recover from. Also, as far as I know, once a class fails to load it can't ever be loaded by the same ClassLoader again.
That said, if you want to show errors to your user in an alert, even if the error occurs before the JavaFX runtime has been initialized, then you need to save the error somewhere. Then, once you launch JavaFX, check wherever you stored the error(s) and show them. For example:
Main.java:
import javafx.application.Application;
public class Main {
public static void main(String[] args) {
// an "error" before JavaFX is launched
App.notifyUserOfError(new RuntimeException("OOPS!"));
Application.launch(App.class, args);
}
}
App.java:
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Queue;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class App extends Application {
private static Queue<Throwable> errorQueue;
private static App appInstance;
public static synchronized void notifyUserOfError(Throwable throwable) {
Objects.requireNonNull(throwable);
if (appInstance == null) {
if (errorQueue == null) {
errorQueue = new ArrayDeque<>();
}
errorQueue.add(throwable);
} else {
if (Platform.isFxApplicationThread()) {
appInstance.showErrorAlert(throwable);
} else {
Platform.runLater(() -> appInstance.showErrorAlert(throwable));
}
}
}
private static synchronized Queue<Throwable> setAppInstance(App instance) {
if (appInstance != null) {
throw new IllegalStateException();
}
appInstance = instance;
var queue = errorQueue;
errorQueue = null; // no longer needed
return queue;
}
private Stage primaryStage;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
var scene = new Scene(new StackPane(new Label("Hello, World!")), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
var errors = setAppInstance(this);
if (errors != null) {
// if non-null then should be non-empty
do {
showErrorAlert(errors.remove());
} while (!errors.isEmpty());
// possibly exit the application if you can't recover
}
}
private void showErrorAlert(Throwable error) {
var alert = new Alert(AlertType.ERROR);
alert.initOwner(primaryStage);
alert.setContentText(error.toString());
var sw = new StringWriter();
error.printStackTrace(new PrintWriter(sw));
var area = new TextArea(sw.toString());
area.setEditable(false);
area.setFont(Font.font("Monospaced", 12));
var details = new VBox(5, new Label("Stack trace:"), area);
VBox.setVgrow(area, Priority.ALWAYS);
alert.getDialogPane().setExpandableContent(details);
alert.showAndWait();
}
}
The above puts the error in a queue if JavaFX has not been initialized yet. At the end of the start method the queue is checked for any errors and they're displayed to the user one after the other. If JavaFX has already been initialized then the error is immediately shown to the user.

How to make a login using a database in intellij idea

so I'm very new to javafx in intellij idea, i have a problem where I have connected with mySQl database in the database section, but now i can't find anywhere how to select everything from my database without having to use a connection string (because i am already connected with the database)
I have already tried several things like just leaving the connection string out but that wouldn't work, I have searched for the answer for a long time now and can't find it anywhere, I hope someone can help me with this.
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.io.IOException;
import java.sql.*;
public class logincontroller extends Application {
public TextField txtusername;
public PasswordField txtpassword;
public Label labeltxt;
public Button btnLogin;
String username, password;
Scene scene1;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public void Login(ActionEvent actionEvent) throws IOException, SQLException {
username = txtusername.getText();
password = txtpassword.getText();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String sql;
sql = "SELECT * FROM users WHERE Inlognaam = 1 AND Wachtwoord = 2";
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
resultSet = preparedStatement.executeQuery(sql);
if (!resultSet.next()) {
labeltxt.setText("Login Failed");
} else {
Parent root1 = FXMLLoader.load(getClass().getResource("Menu.fxml"));
Stage secondarystage = new Stage();
secondarystage.setScene(new Scene(root1));
secondarystage.show();
Stage stage = (Stage) btnLogin.getScene().getWindow();
stage.close();
}
txtusername.setText("");
txtpassword.setText("");
}
}
this is what i already have at this moment
In Response to #GhostCat This should help you get started. Make sure however that after using the Connection you close it. Same with PreparedStatments always close them if youre not using them.
import java.sql.DriverManager;
import java.sql.SQLException;
public class Connector {
public Connection con;
private final String URL = "jdbc:mysql://localhost:3306/dbname";
private final String USERNAME = "username";
private final String PASSWORD = "password";
/*
* Adds DB Connection
*/
public void add() {
try {
con = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException se) {
se.printStackTrace();
}
}
}```
You don't want to leave your connection open. You want to connect, select, then close. Please research "Try with Resources" for how to do this properly.
Typically a web server handles sessions so please forgive me for this answer.
What you can do is add a token, ID, secret code, to your Users table that gets sent back to the client. Then in the next controller after your secondary stage loads, you need to do a second connection to the database and a new sql query using the secret code for that user. This way, your database can only return records intended for that specific user.

Open External Application From JavaFX

I found a way to open a link on default browser using HostServices.
getHostServices().showDocument("http://www.google.com");
Is there any way to open a media in default media player?
Is there any way to launch a specific File or Application?
Generally speaking, you can use Desktop#open(file) to open a file natively as next:
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.OPEN)) {
desktop.open(file);
} else {
throw new UnsupportedOperationException("Open action not supported");
}
Launches the associated application to open the file. If the specified
file is a directory, the file manager of the current platform is
launched to open it.
More specifically, in case of a browser you can use directly Desktop#browse(uri), as next:
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
desktop.browse(uri);
} else {
throw new UnsupportedOperationException("Browse action not supported");
}
Launches the default browser to display a URI. If the default browser
is not able to handle the specified URI, the application registered
for handling URIs of the specified type is invoked. The application is
determined from the protocol and path of the URI, as defined by the
URI class. If the calling thread does not have the necessary
permissions, and this is invoked from within an applet,
AppletContext.showDocument() is used. Similarly, if the calling does
not have the necessary permissions, and this is invoked from within a
Java Web Started application, BasicService.showDocument() is used.
If you want to either open a URL which has an http: scheme in the browser, or open a file using the default application for that file type, the HostServices.showDocument(...) method you referenced provides a "pure JavaFX" way to do this. Note that you can't use this (as far as I can tell) to download a file from a web server and open it with the default application.
To open a file with the default application, you must convert the file to the string representation of the file: URL. Here is a simple example:
import java.io.File;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class OpenResourceNatively extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField("http://stackoverflow.com/questions/39898704");
Button openURLButton = new Button("Open URL");
EventHandler<ActionEvent> handler = e -> open(textField.getText());
textField.setOnAction(handler);
openURLButton.setOnAction(handler);
FileChooser fileChooser = new FileChooser();
Button openFileButton = new Button("Open File...");
openFileButton.setOnAction(e -> {
File file = fileChooser.showOpenDialog(primaryStage);
if (file != null) {
open(file.toURI().toString());
}
});
VBox root = new VBox(5,
new HBox(new Label("URL:"), textField, openURLButton),
new HBox(openFileButton)
);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private void open(String resource) {
getHostServices().showDocument(resource);
}
public static void main(String[] args) {
launch(args);
}
}
Only the solution with java.awt.Desktop worked for me to open a file from JavaFX.
However, at first, my application got stuck and I had to figure out that it is necessary to call Desktop#open(File file) from a new thread. Calling the method from the current thread or the JavaFX application thread Platform#runLater(Runnable runnable) resulted in the application to hang indefinitely without an exception being thrown.
This is a small sample JavaFX application with the working file open solution:
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileOpenDemo extends Application {
#Override
public void start(Stage primaryStage) {
final Button button = new Button("Open file");
button.setOnAction(event -> {
final FileChooser fileChooser = new FileChooser();
final File file = fileChooser.showOpenDialog(primaryStage.getOwner());
if (file == null)
return;
System.out.println("File selected: " + file.getName());
if (!Desktop.isDesktopSupported()) {
System.out.println("Desktop not supported");
return;
}
if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
System.out.println("File opening not supported");
return;
}
final Task<Void> task = new Task<Void>() {
#Override
public Void call() throws Exception {
try {
Desktop.getDesktop().open(file);
} catch (IOException e) {
System.err.println(e.toString());
}
return null;
}
};
final Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The other proposed solution with javafx.application.HostServices did not work at all. I am using OpenJFX 8u141 on Ubuntu 17.10 amd64 and I got the following exception when invoking HostServices#showDocument(String uri):
java.lang.ClassNotFoundException: com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory
Obviously, JavaFX HostServices is not yet properly implemented on all platforms. On this topic see also: https://github.com/Qabel/qabel-desktop/issues/420

How to create multiple javafx controllers with different fxml files?

I've been looking at some blogs and other stackoverflow questions, and I'm not seeing a direct answer to my question. I am creating a javafx gui client and I want to have my menubar be one controller in one fxml and then i want the content area to be additional fxml files. The login screen will be one fxml, after the login screen will be the main content of the application and that will be in one fxml. How do i go about doing this?
I just don't want to have all of my code for my login, menubar, and main content in the same file. This is an image of what i am working on:
Use FXML as components by using a custom java class as fx:root and as fx:controller of your FXML file: http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
To do so, you need to call in the constructor of your custom java class FXMLLoader which will load your FXML.
The advantage is to change the way FXML load components.
The classic way to instanciate components via FXMLLoader with nested controllers is: FXML first, then controller for each part.
With this technique this is: controller first, then FXML for each component. And you won't load FXML in FXML directly, you will import your custom java classes in the FXML.
This is a better abstraction (no need to know how a component is implemented when you import them in FXML) and helps reusing code as it is like implementing a custom widget with FXML support. To make your component reusable, make sure your implementation doesn't have tight coupling with other parts, or use IOC to do so (for instance, with Spring integration with JavaFX). This way, you will be able to import your component in any part of your application (just like a DateInput widget) without worry and you won't duplicate code.
In your case you will have:
public class MenuBox extends VBox {
#FXML
private LoginBox loginBox;
#FXML
private ProfilesBox profilesBox;
public MenuBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public class LoginBox extends VBox {
public LoginBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public class ProfilesBox extends VBox {
public ProfilesBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
And you will import LoginBox and ProfilesBox in menu.fxml that manages the global layout for your page:
<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
xmlns:fx="http://javafx.com/fxml">
<!-- Stuff here to declare the menu bar-->
<HBox>
<ProfilesBox fx:id="profilesBox"/>
<LoginBox fx:id="loginBox"/>
</HBox>
</fx:root>
login.fxml and profiles.fxml contain just basic components.
You can include FXML documents one within the other - this should help you with separating the design logic
This means you can have Nested Controllers - one for each document.
From the documentation, you can now setup your code such that logic can be separated as well as invoked from the root controller (if need be).
Hope that helps.
I needed a popup window with similar requirements (more control over the nodes and the layout).
Having worked my way through the recommendations, I found a solution that might be useful.
First, I created a second fxml document and second controller (in NetBeans, New -> Empty FXML ... -> Use Java Controller -> Create New ...).
A little challenging was to figure out how to build the stage in the main controller and connect it to the popup controller.
The link Passing Parameters JavaFX FXML gives some real good insights and techniques.
The final code looks like this (I hope it can help someone):
// Anchor Pane from the popup
#FXML
AnchorPane anchorPanePopup;
#FXML
private void soneButtonAction(ActionEvent event) throws IOException {
Stage newStage = new Stage();
AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
Scene scene = new Scene(anchorPanePopup);
newStage.setScene(scene);
newStage.initModality(Modality.APPLICATION_MODAL);
newStage.setTitle("Dialog Window");
newStage.showAndWait();
}
package javafxapplication11;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
public class FXMLDocumentController implements Initializable {
#FXML
private CheckBox c1;
#FXML
private CheckBox c2;
public void clicked1(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
public void clicked2(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
public void clicked3(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
}

Categories

Resources