Not switching to next FXML file? - java

Im making a button that switches to the next scene in Javafx, ie switching to the next FXML file.
Here is the code:
public void submitorder(ActionEvent actionEvent) throws IOException {
Customer cust = new Customer();
cust.setOrder(order);
tbl.getCustomers().add(cust);
if (tbl.getCustomers().size() == noOfDiners) {
System.out.println("if statement");
allcustomers = tbl.getCustomers();
try{
System.out.println("This prints");
Window mainWindow = btnSubmitOrder.getScene().getWindow();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("paymentScreen.fxml"));
Parent root = loader.load();
System.out.println("test");
PaymentScreenController psc = loader.getController();
psc.dataReceiver(allcustomers);
mainWindow.getScene().setRoot(root);
} catch(Exception e){
System.out.println(e.getMessage());
}
}
lvOrder.getItems().clear();
}
So that first print statement in the try method prints out so it goes into the try method but it still doesnt switch the scene. Ive used this exact code elsewhere in my program and it works so it dont know what im doing wrong.
Ive also tried not using a try method but i just get an error. In this case nothing happens
That if statement is also correct
Any help would be appreciated thanks

Related

Closing the stage from JavaFX FXML controller class (ConfirmBox)

I'm a beginner in JavaFX, and I am developing a simple app and need to create a confirm box for closing the stage. I have done it without a problem without FXML when I have in the same method the initializing and the closing of the stage. But when I do it with FXML, when I have opened the stage in another class it fails to close it from controller class, even if I create a global stage instance.
public class ConfirmBox {
private Stage confirmBoxStage = new Stage();
boolean confirmClose;
// Confirm box -----------------------------------------------------------------------------------------------------
public boolean confirmClose() {
Parent rootConfirmBox = null;
confirmBoxStage.initModality(Modality.APPLICATION_MODAL);
try {
rootConfirmBox = FXMLLoader.load(getClass().getResource("ConfirmBox.fxml"));;
} catch (IOException e) {
System.out.println("Exception ConfirmBox.java//confirmBoxScene");
e.printStackTrace();
}
Scene confirmBoxScene = new Scene(rootConfirmBox, 640, 480);
confirmBoxStage.setScene(confirmBoxScene);
confirmBoxStage.showAndWait();
return confirmClose;
}
// Closing the confirm box -----------------------------------------------------------------------------------------
public void closeConfirmBox() {
confirmBoxStage.close();
}
}

JavaFX switch to different scenes with one button

I was creating an application and wanted to change screens with one button depending on a number the user inputs. For example, if a user enters "1234", the program checks another class to see if that number is there. If it is, you go on to SceneOne. If the number the user enters is in reverse compared to the number in the other class, then you go to SceneTwo. However, when I try to set the location to a different scene, it just ignores it and automatically sends me to the first screen.
Storage.Java (contains a pre-defined number)
int pin = 1234;
public int getPin() {
return number;
}
My other class: (function executes when button it is assigned to is pushed)
public void switchScenes(ActionEvent e) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/application/ScreenOne.fxml"));
Parent changeScenes = loader.load();
Scene firstScene = new Scene(changeScenes);
Stage window = (Stage)((Node)e.getSource()).getScene().getWindow();
Storage a = new Storage();
int pin = a.getPin();
if(Integer.parseInt((screen.getText())) == pin) {
//screen is a field where user can enter a number
window.setScene(firstScene);
window.show();
}
else if(Integer.parseInt(screen.getText()) == reverseNumber(pin)) {
//if number entered is in reverse, change to ScreenTwo
loader.setLocation(getClass().getResource("/application/ScreenTwo.fxml"));
}
I can offer a format for changing the scene on a single stage:
On the sixth line is the desired .fxml object. You can simply make an if-then statement and load whatever .fxml object you want based on the input. This is a proven snippet of code I rely on when I want to change the scene in my projects.
{
#FXML
public void buttonclicked(ActionEvent event) throws IOException //This method loads a new scene in a current window
{
//note that on this line you can substitue "Screen2.fxml" for a string chosen prior to this line.
Parent loader = FXMLLoader.load(getClass().getResource("Screen2.fxml"));//Creates a Parent called loader and assign it as ScReen2.FXML
Scene scene = new Scene(loader); //This creates a new scene called scene and assigns it as the Sample.FXML document which was named "loader"
Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); //this accesses the window.
app_stage.setScene(scene); //This sets the scene as scene
app_stage.show(); // this shows the scene
}
}

JavaFX-SceneBuilder - Can't access fx:id when opening new window

I have this code (part of a quite big application):
The following function is located in the controller class of the project.
public void callSearch(){
Stage supplyStage = new Stage();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("supplyResult.fxml"));
supplyStage.setTitle("Supply Result Set");
supplyStage.setScene(new Scene(root, 1400, 900));
supplyStage.show();
} catch (IOException e) {
e.printStackTrace();
}
try {
typeColumn.setCellValueFactory(new PropertyValueFactory<Supply, String>("type"));
nameColumn.setCellValueFactory(new PropertyValueFactory<Supply, String>("name"));
dateColumn.setCellValueFactory(new PropertyValueFactory<Supply, String>("order_date"));
pricePerUnitColumn.setCellValueFactory(new PropertyValueFactory<>("pricePerUnit"));
quantityColumn.setCellValueFactory(new PropertyValueFactory<>("quantity"));
}
catch (NullPointerException npe){
System.out.println("Null...");
}
searchSupplyStartDate = java.sql.Date.valueOf(startDateDatePicker.getValue());
searchSupplyEndDate = java.sql.Date.valueOf(endDateDatePicker.getValue());
tableOutput.setItems(myMain.getSupplies(searchSupplyStartDate,searchSupplyEndDate,null,null));
}
My problem is that I get a NullPointerException in the line typeColumn.setCellValueFactory(new PropertyValueFactory<Supply, String>("type"));
In previous version of the application I had the columns in the same window as the rest of the scene. Now I try to add a second window when displaying the same stuff, to make the first scene a bit more beautiful. (the code was working when I had one scene).
In fact, to make things clear, i want with the press of a button, the function callSearch() to be called. Then a window appears, with a table of 5 columns attached: typeColumn, nameColumn, dateColumn, pricePerUnitColumn, quantityColumn. Those 5 columns are declared in the (only) controller of the project, so i thought that they are visible in any fxml file in the project, but that's not the case.
Does anybody know what am I missing? the typeColumn is visible from the SupplyResult.fxml in scene builder, but does not seem to execute the code it has to...

Load FXML in initialize()

I'm creating my first JavaFX application, and I'm doing OK so far. I'm just encountering one problem.
For displaying and loading FXML files I'm using a VistaNavigator class found on StackOverflow:
public static void loadVista(String fxml) {
try {
mainController.setVista(
FXMLLoader.load(
VistaNavigator.class.getResource(
fxml
)
)
);
} catch (IOException e) {
e.printStackTrace();
}
}
I have a ScanController, which receives input from the keyboard and checks a ticket ID based on this input. When the ticket is OK, it loads "scan-success.fxml", otherwise it loads "scan-failure.xml", each of these FXML-files have an own controller. I'm loading the success FXML like this:
VistaNavigator.loadVista(VistaNavigator.VISTA_SCAN_SUCCESS);
This is working great. The Success-FXML page is showing and the ScanSuccessController is loading. In the initialize() method of ScanSuccessController.java I have the following code snippet:
try {
Thread.sleep(2000); //1000 milliseconds is one second.
VistaNavigator.loadVista(VistaNavigator.VISTA_SCAN_HOME);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
So I would like to show the success-page for about 2 seconds, and then head back to the home screen (scan-home.fxml with controller ScanHomeController.java) to scan some more tickets. However, when executing this code, just 'nothing' happens, no exception and no change of FXML-file.
When I try to load a new vista after clicking a button (in an EventHandler) it works great.
I can imagine that JavaFX is not able to load a new FXML-file before the controller has been fully initialised, but cannot figure out where to put this line of code..
I hope someone can help me out with this.
What about this:
#Override
public void initialize(URL url, ResourceBundle rb) {
Timeline timeline=new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(2),
e->VistaNavigator.loadVista(VistaNavigator.VISTA_SCAN_HOME)));
timeline.play();
}
Note that by using a Timeline everything runs in the JavaFX thread.

What is best way to pass object in JavaFX scene

(note, what i newbie in java)
I a little bit stuck in solving the problem of pass object between javafx scenes and classes.
For example, i have class, which waits for data by server; main class and 2 javafx windows.
Let it looks like this:
Listener.java.
Let it work at another thread. When we got "nelo" from server, then it'll means, what user not logged it, and then, we should open Login Window
// some package
// some imports
public class Listener extends Thread {
public void run() {
System.out.println("[INF] Wait for server...");
while(true) {
handle();
}
}
public void handle()
{
try {
byte[] token = new byte[6];
DataInputStream src = new DataInputStream(in);
src.read(token);
String token_val = new String(token);
switch (token_val) {
case "_nelo_":
System.out.println("[INF] Auth required");
break;
}
} catch (IOException e) {
}
}
}
Okay, there nothing weird. Just simple class for listening.
But here my troubles started. I try to explain it. (previosly, Sorry for bad english, i still learn this language)
Lets create login window (imagine that fxml file and controller created :) ):
// some package
// some imports
public class WindowLogin extends Application{
private Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = new Stage();
try {
URL location = getClass().getResource("../views/WindowLogin.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = (Parent) fxmlLoader.load(location.openStream());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void show(){
launch();
}
}
So, when user open application, client will try connect to server.
If connection success, then server ask client for auth (Show login window). Next - user enter login and pass and click "Login" button. (Login Window show some indication of proccess). If auth success - Hide login, else - show some info in window.
As a result, i need access from Listener to Login window Controller. i.e. as i wrote before - different answer from server - different elements displayed.
How i can realize access to LoginWindowController ?
Thanks in advance
I will give you basic guidance for each task:
Connection
If connection with the server is successful then:
Platform.runLater(new Runnable() {
public void run() {
try {
WindowLogin login = new WindowLogin();
login.start(new Stage());
} catch (Exception e) {
e.printStackTrace();
}
}
});
Login
Error
You set a blank label on the WindowController and if the user cound't autheticate, than you fill this label.
Succesful login
You could use the same Platform.runLater as I used it before, or you could do something using stackpane and changing it's order ( I strongly recommend to use the Platform.runLater).

Categories

Resources