I am sorry to ask this silly question. I am unable to solve it and I need guidance.
In my application I start my main java code with menu as
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("MONC GUI :: Abhijit Bhattacharyya");
FXMLLoader loader = new FXMLLoader(MoncGUI.class.getResource("RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
//Scene scene = new Scene(rootLayout);
rootScene = new Scene(rootLayout);
primaryStage.setScene(rootScene);
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
}
......
Then I opt to go to a particular menu page by opening another fxml in the main class as
public void GeomStart() {
try {
FXMLLoader loader = new FXMLLoader(MoncGUI.class.getResource("Geom.fxml"));
AnchorPane geomPage = (AnchorPane)loader.load();
rootLayout.setCenter(geomPage);
GeomController controller = loader.getController();
controller.setMyScene(rootScene);
} catch (IOException ex) {
System.out.println(" Problem in loading geometry set");
Logger.getLogger(MoncGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
The geom.fxml is associated with geomController.java which puts a primitive geometric form on the screen and I want it to be rotated. I find mouseHandler code in the internet which should be activated as screen is passed.
I am confused which screen should I pass. Is it the root screen initiated by the main class at the start or I need to define a new screen locally here in this controller. I tried with a screen local to this controller yet the code handle is not passed to MouseHandler code.
Thanks and Regards
There is no need to pass the scene arround at all. Inside your controller you have access to the nodes which you have defined in your FXML file. Once this file is loaded and you have attached its root node to the scene graph you can get the scene by calling the .getScene() method of any of these nodes.
Related
How do I display an fxml file for some seconds and close that fxml file and return to the mainpage.fxml?
I have tried to add hideThispage method to the initialize method in the controller class of the fxml but I guess the initialize methods just runs before the class is actually loaded so I cannot run this code.
#FXML
public void hideThisPage() throws InterruptedException, IOException {
Window window = new Stage();
PauseTransition pause = new PauseTransition(Duration.seconds(5));
pause.setOnFinished(e -> window.hide());
pause.play();
FxmlDisplay fxmlDisplay = new FxmlDisplay();
fxmlDisplay.stageSelection("View/Main.fxml");
}
To return to the main.fxml or any fxml I have a method that I call:
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(path));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
In my case, I have a print button in my printreceipt.fxml file that prints the contents. Then it switches to the printpage.fxml ( i am able to switch to the page) But my problem is the printpage.fxml is supposed to be displayed only for 5 seconds and close. then it should go back to main.fxml. how and where do I call the hidethisPage() method?
#FXML
void printRandomTicket(ActionEvent event) throws SQLException, ClassNotFoundException, JRException, IOException, InterruptedException {
FxmlDisplay fxmlDisplay = new FxmlDisplay();
((Node) event.getSource()).getScene().getWindow().hide();
fxmlDisplay.stageSelection("/View/Dialogs/PrintingTicket.fxml");
GenerateTicket generateTicket = new GenerateTicket();
generateTicket.generateTicket();
PrintTicket printTicket = new PrintTicket();
printTicket.printTicket();
}
I hope this clarifies it.
I have a project in school where I have to develop a program where you first can choose whether you want to save/read to/from a SQL DB or to save/read to/from XML.
I've made a GUI where you can choose between both methods.
The GUI closes after the user clicks on one of the buttons and the MainMenu GUI opens.
Now I need to know in the MainMenuController what the user choose.
I found online a Method to call the MainMenuController inside the first controller, with FXMLLoader.getController().
try {
Stage stage = new Stage();
FXMLLoader Loader = new FXMLLoader();
Parent root = Loader.load(getClass().getResource("MainMenu.fxml"));
MainMenuController mc = Loader.getController();
mc.setSave("sql");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
catch (Exception e) {
e.printStackTrace();
}
MainMenuController
public class MainMenuController {
private String save = null;
public void setSave(String save) {
this.save=save;
}
public String getSave() {
return save;
}
}
But when i try to access a method in MainMenuController I get a NullPointerException for
mc.setSave("sql")
First ,to understand this issue ,you should make some tricks to detect where is your problem.When you do :
System.out.println(mc);
You will find the result is null.So you can not call setSave("sql") with null object,you got a null controller because your did not specify the location of your file,but you can change some lines to resolve your problem :
try {
Stage stage = new Stage();
FXMLLoader fxm = new FXMLLoader(getClass().getResource("MainMenu.fxml"));
Parent parent = (Parent) fxm.load();
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
FirstController mc = fxm.getController();
System.out.println(mc);
mc.setSave("sql");
} catch (Exception e) {
e.printStackTrace();
}
You are calling the static method FXMLLoader.load(URL). Because this is a static method, it has no effect on the state of the FXMLLoader instance you created; specifically the controller field is not set.
Instead, set the location on the FXMLLoader instance, and call the instance method load():
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainMenu.fxml"));
// or just FXMLLoader loader = new FXMLLoader(getClass().getResource("MainMenu.fxml"));
Parent root = loader.load();
Hello I have a procedure who load a stage like this :
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource(ConstantsUI.CHEMIN_VIEW+
ConstantsUI.ECRAN_CAISSE_FERMEE));
AnchorPane ecran = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(ecran);
MainApp.getInstance().getPrimaryStage().setScene(scene);
genericController = loader.getController();
genericController.setStage(MainApp.getInstance().getPrimaryStage());
// on garde la fenĂȘtre en premier plan
MainApp.getInstance().getPrimaryStage().setMaximized(true);
MainApp.getInstance().getPrimaryStage().show();
MainApp.getInstance().getPrimaryStage().showAndWait();
System.out.println("toto");
And I have an button with this code :
#FXML
public void clickButton() {
System.out.println("------here-----");
stage.close();
}
My problem is, that after I clicked on my button, the message "toto" is not visible. Why ?
Thanks.
Calling showAndWait is not allowed for the primary stage.
From the javadoc
Throws:
[...]
IllegalStateException - if this method is called on the primary stage.
You could instead use a onHidden event handler:
MainApp.getInstance().getPrimaryStage().setOnHidden(evt -> {
System.out.println("toto");
});
MainApp.getInstance().getPrimaryStage().show();
Alternatively if you want to run the code after the last window of the application has been closed (asumming you didn't use Platform.setExplicitExit(false)), you could override Application.stop():
#Override
public void stop() throws Exception {
System.out.println("toto");
}
This seems like it should be easy, so I must be missing something obvious: I have 4 standalone applications in the same package, us.glenedwards.myPackage,
myClass1 extends Application
myClass2 extends Application
etc...
I need each class to act as its own standalone application. Yet I want to be able to start the other 3 classes from the one I'm in by clicking a link. Android allows me to do this using Intents:
Intent intent = new Intent(this, EditData.class);
overridePendingTransition(R.layout.edit_data_scrollview, R.layout.state);
startActivity(intent);
I've tried starting myClass2 from myClass1 using
myClass2.launch("");
But I get an error, "Application launch must not be called more than once". The only way I can get it to work is if I remove both "extends application" and the start() method from myClass2, which means that myClass2 is no longer a standalone application.
How can I start myClass2, myClass3, or myClass4 from myClass1 with all 4 of them being standalone applications?
You can make this work by calling start(...) directly on a new instance of one of the Application subclasses, but it kind of feels like a bit of a hack, and is contrary to the intended use of the start(...) method. (Just semantically: a method called start in a class called Application should be executed when your application starts, not at some arbitrary point after it is already running.)
You should really think of the start method as the replacement for the main method in a traditional Java application. If you had one application calling another application's main method, you would (hopefully) come to the conclusion that you had structured things incorrectly.
So I would recommend refactoring your design so that your individual components are not application subclasses, but just plain old regular classes:
public class FirstModule {
// can be any Parent subclass:
private BorderPane view ;
public FirstModule() {
// create view; you could also just load some FXML if you use FXML
view = new BorderPane();
// configure view, populate with controls, etc...
}
public Parent getView() {
return view ;
}
// other methods as needed...
}
and, similarly,
public class SecondModule {
private GridPane view ;
public SecondModule {
view = new GridPane();
// etc etc
}
public Parent getView() {
return view ;
}
}
Now you can just do things like
FirstModule firstModule = new FirstModule();
Scene scene = new Scene(firstModule.getView());
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
anywhere you need to do them. So you can create standalone applications for each module:
public class FirstApplication extends Application {
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new FirstModule().getView());
primaryStage.setScene(scene);
primaryStage.show();
}
}
or you can instantiate them as part of a bigger application:
public class CompositeModule {
private HBox view ;
public CompositeModule() {
Button first = new Button("First Module");
first.setOnAction(e -> {
Parent view = new FirstModule().getView();
Scene scene = new Scene(view);
Stage stage = new Stage();
stage.initOwner(first.getScene().getWindow());
stage.setScene(scene);
stage.show();
});
Button second = new Button("Second Module");
second.setOnAction(e -> {
Parent view = new SecondModule().getView();
Scene scene = new Scene(view);
Stage stage = new Stage();
stage.initOwner(second.getScene().getWindow());
stage.setScene(scene);
stage.show();
});
HBox view = new HBox(10, first, second);
view.setAlignment(Pos.CENTER);
}
public Parent getView() {
return view ;
}
}
and
public class CompositeApplication extends Application {
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new CompositeModule().getView(), 360, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
}
The way I think of this is that Application subclasses represent an entire running application. Consequently it makes sense only to ever instantiate one such class once per JVM, so you should consider these inherently not to be reusable. Move any code you want to reuse into a different class somewhere.
have you tried this?
Runtime.getRuntime().exec("myClass1 [args]"); //put all args as you used in command
Also, handle/catch the exceptions, as needed.
I was right; it was a no-brainer. That's what I get for writing code on 4 hours of sleep:
myClass2 class2 = new myClass2();
try {
class2.start(stage);
} catch (Exception e) { e.printStackTrace(); } }
I have a stage with these properties
stage = new Stage(StageStyle.DECORATED);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.setTitle("My App");
stage.getIcons().add(new Image(icon-address));
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("start.fxml"));
fxmlLoader.setController(this);
...
...//and other properties
It is in full screen in this stage. I have a button and each time I click on it , a method of another class is called and the reference of this stage is passed to it.
For example, if I have two classes Start and ButtonClicked
In Start, I have this :
Button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
buttonClicked a = new buttonClicked ();
try {
a.render(stage);
} catch (Exception ex) {
Logger.getLogger(menuController.class.getName())
.log(Level.SEVERE, null , ex);
}
}
});
Now, the render method is called and I have the following code inside render :
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("buttonclicked.fxml"));
fxmlLoader.setController(this);//set Controller for our fxml file
loader = fxmlLoader.load();//loader is a stackPane because buttonclick.fxml has stackPane
stage.setScene(new Scene(loader));
stage.setFullScreen(true);
...
The problem is, if user clicks on button, stage become a 1024x700(because i have pictures in start.fxml and buttonclicked.fxml. The size of both the picture is 1024x700
After a moment, it becomes full screen. How can i fix this ?
I want to kill the delay in full screen
Thanks
Try
stage.getScene().setRoot(loader);
in render method.
By doing this, the creation of a new scene is eliminated. Therefore I guess, some UI related updates and calculations that must be done after the scene has been shown, are also eliminated.