Switching scene in javaFX - java

I have problem when trying to close current scene and open up another scene when menuItem is selected. My main stage is coded as below:
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Shop Management");
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource
("createProduct.fxml"));
Scene myScene = new Scene(myPane);
primaryStage.setScene(myScene);
primaryStage.show();
}
Then within createProduct.fxml, when menuItem is onclick, it will perform this:
public void gotoCreateCategory(ActionEvent event) throws IOException {
Stage stage = new Stage();
stage.setTitle("Shop Management");
Pane myPane = null;
myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
Scene scene = new Scene(myPane);
stage.setScene(scene);
stage.show();
}
It does opened up createCategory.fxml. However, the previous panel which is createProduct.fxml does not close. I know there's something called stage.close() to do this but I have no idea where to implement it since I not passing the scene from main right from the start. I wonder how should I fix this.
Thanks in advance.

You have to make some changes in start method, like..
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Shop Management");
FXMLLoader myLoader = new FXMLLoader(getClass().getResource("createProduct.fxml"));
Pane myPane = (Pane)myLoader.load();
CreateProductController controller = (CreateProductController) myLoader.getController();
controller.setPrevStage(primaryStage);
Scene myScene = new Scene(myPane);
primaryStage.setScene(myScene);
primaryStage.show();
}
and your CreateProductController.java will be,
public class CreateProductController implements Initializable {
Stage prevStage;
public void setPrevStage(Stage stage){
this.prevStage = stage;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void gotoCreateCategory(ActionEvent event) throws IOException {
Stage stage = new Stage();
stage.setTitle("Shop Management");
Pane myPane = null;
myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
Scene scene = new Scene(myPane);
stage.setScene(scene);
prevStage.close();
stage.show();
}
}

You have multiple ways to solve your problem, few of them I tell you. What I understood from your question is that you want to create an application which contains a navigation (menu bar) on the top and by using it user can switch to any screen.
The easiest method is to make your Navigation Bar available globally, either by you make it static or by passing it to screens, or by any other method. Second, make a single screen (say Border Pane) and load other screens on it (its center).
You can also use spring integration in project so that it provide you better injection of controllers. See Ref : http://www.zenjava.com/2011/10/25/views-within-views-controllers-within-controllers/
You can also create your own single screen controller and manage other screens using that.
See Ref: https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1
But for this (above) you have to change or update your current architecture.

you can get the current open window/stage from the fx:id . just make sure you have an item in your createProduct.fxml that has fx:id like below
<TextField fx:id="username" labelFloat="true" layoutX="80.0" layoutY="300.0" prefHeight="32.0" prefWidth="260.0" promptText="Login Username" />
Hope you see the fx:id attribute.
Then in your start controller, leave as it is
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Shop Management");
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource("createProduct.fxml"));
Scene myScene = new Scene(myPane);
primaryStage.setScene(myScene);
primaryStage.show();
}
Then in your CreateProductController.java
//make sure you import the javafx item you have used, eg have used TextField
import javafx.scene.control.TextField;
public class CreateProductController implements Initializable {
// make sure the variable has the same type as the item in the fxml "TextField" and same name "username"
#FXML
private TextField username;
//we use the above variable since its referencing the window to which it belongs because of the fx:id attribute, then we close it
private void closeStage()
{
((Stage) username.getScene().getWindow()).close();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void gotoCreateCategory(ActionEvent event) throws IOException {
closeStage();// we close the old stage
Stage stage = new Stage();
stage.setTitle("Shop Management");
Pane myPane = null;
myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
Scene scene = new Scene(myPane);
stage.setScene(scene);
stage.show();
}
}

Related

Switch between scenes in fullscreen mode JavaFX [duplicate]

I have read several questions/solutions here that are related to my problems. but nothing seems to work.
so I have a primarystage in fullscreen mode, say if i click a button it changes the scene. but the stage seems to display the taskbar. also I resolved the issue by adding this to all of the scene methods..
stage.setFullScreen(false);
stage.setFullScreen(true);
BUT, the transition in scenes is not that fluid. first it goes to desktop and back to fullscreen.. which is not the ideal solution.
here is my code for the primary stage:
public static Stage stage;
private static AnchorPane mainLayout;
#Override
public void start(Stage primaryStage) throws IOException
{
Main.stage = primaryStage;
Main.stage.setTitle("Raven App");
stage.initStyle(StageStyle.UNDECORATED);
stage.setFullScreen(true);
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
Main.showMain();
}
here is my code for changing the scene:
public static void UserLogin() throws IOException
{
FXMLLoader loader=new FXMLLoader();
loader.setLocation(Main.class.getResource("page/UserHomeLogin.fxml"));
mainLayout=loader.load();
Scene scene=new Scene(mainLayout);
stage.setScene(scene);
stage.show();
}
I don't know if this is a bug or something. But i thought if you set your primary stage to full screen. and should be fullscreen all through out regardless of scene.
also, if i have a primary stage in full screen mode.. and a secondary stage NOT in full screen mode. the primary stage seems to disappear if i click a button to show the secondary stage. I wanted to show the secondary page on top of the primary stage, and the primary stage should not be clickable unless the secondary page is closed.
my code for showing the secondary stage:
public static void PasswordVerify() throws IOException
{
Stage stage = new Stage();
Parent root = FXMLLoader.load(Main.class.getResource("page/PassConfirm.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("popup window");
stage.initModality(Modality.APPLICATION_MODAL);
stage.showAndWait();
stage.show();
}
Instead of creating a new scene, just change the root of the existing scene:
public static void UserLogin() throws IOException {
FXMLLoader loader=new FXMLLoader();
loader.setLocation(Main.class.getResource("page/UserHomeLogin.fxml"));
mainLayout=loader.load();
stage.getScene().setRoot(mainLayout);
// or just
// scene.setRoot(mainLayout);
// if you already have a reference to the scene
}
The second thing you are asking is not really possible. In JavaFX, on many platforms "full screen mode" is really implemented as "exclusive screen mode"; so there is a unique window visible. So you would need another solution entirely to this, that didn't involve displaying a new window at all.

In Javafx when a window is opened how can i set it so that the user isnt able to open the same window again?

I tried a lot but just couldn't find any solution. At the moment the opened window(popup window) is always on top but the user can still access the main window. That's how it should be, but it shouldn't be possible to open the same popup window again.
Stage stage = new Stage();
stage.setTitle(panelTitle);
stage.setScene(new Scene(root));
stage.initModality(Modality.WINDOW_MODAL);
stage.setAlwaysOnTop(true);
stage.showAndWait();
Thank you in advance!
As LazerBanana said, I would disable the button that opens the window, and I would enable it when you close it.
Stage stage = new Stage();
button.setDisable(true);
stage.setTitle(panelTitle);
stage.setScene(new Scene(root));
stage.initModality(Modality.WINDOW_MODAL);
stage.setAlwaysOnTop(true);
stage.showAndWait();
// your logic here
button.setDisable(false);
An alternative solution to creating a new one each time is to create one and just setup and show.
public class Stack extends Application {
private final Stage popup = new Stage();
#Override
public void start(Stage stage) throws Exception {
BorderPane root = new BorderPane();
root.setPrefWidth(400);
root.setPrefHeight(200);
Button button = new Button("ClickMePopup");
root.setCenter(button);
button.setOnAction(
event -> {
if (!popup.isShowing()) {
// you dont set modality because after the stage is set to visible second time it will throw an exception.
// Again depends on what you need.
// popup.initModality(Modality.WINDOW_MODAL);
// this focuses the popup and main window is not clickable
// popup.initOwner(stage);
VBox dialogVbox = new VBox(20);
dialogVbox.getChildren().add(new Text("Some Dialog"));
Scene dialogScene = new Scene(dialogVbox, 300, 200);
popup.setScene(dialogScene);
// you can actually put all above into the method called initPopup() or whatever, do it once, and just show it here or just bind the property to the button.
popup.show();
}
});
Scene scene = new Scene(root);
stage.setTitle("Stack");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Or disable the button when clicked, but if your popup is not driven by the button or can be opened from other places the first idea would be a bit better in my opinion. Depends on what you need.
Or just create your own class and Springify it.

Java FX, switching scenes messes up node alignment of second scene?

Im working on a java FX application were I switch between my start up scene, startScreen() and my game play scene, create(). I have looked at multiple tutorials on how to switch scenes to make sure I had the right idea, and it seems simple enough.
However, if I start the application with the create() scene the format and alignment of all the nodes within are fine. If I try to start with the startScreen() scene and then switch to the create() using the action event, the alignment of the nodes in the game play scene gets messed up (the boards shift and the labels are placed on top of the boards). As far as I've seen in tutorials, switching scenes shouldn't affect the alignment of nodes of scenes assuming the scenes normally work separately.
Original (just calling create()) and Second Version calling both startScreen() and create()
public Parent create() {
BorderPane root = new BorderPane();
root.setPrefSize(800, 800);
setButtons(root);
enemy = new Board(event -> {...}, true);
player = new Board(event -> {...}, false);
VBox vbox = new VBox(50, enemyLabel, enemy, playerLabel, player);
vbox.setAlignment(Pos.CENTER);
root.setCenter(vbox);
return root;
}
public Parent startScreen(Stage primaryStage) {
BorderPane pane = new BorderPane();
pane.setPrefSize(800, 800);
pane.setId("pane");
Button button = new Button("START");
button.setOnAction(e-> primaryStage.setScene(new Scene(create())));
pane.setCenter(button);
return pane;
}
#Override
public void start(Stage primaryStage) {
try {
primaryStage.setTitle("Boat Wars");
primaryStage.setResizable(false);
//Scene scene = new Scene(startScreen(primaryStage));
//scene.getStylesheets().addAll(this.getClass().getResource("application.css").toExternalForm());
Scene scene = new Scene(create());
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}

Java FX Disable Stage Maximisation Animation

When I open a new window in my application and maximise it using newStage.setMaximized(true); it shows the animation of the window increasing in size from the default size to the size of the screen, is there any way to disable this animation and swiftly move from one fullscreen window to another upon button click?
Here's my code:
public class HomeController {
#FXML private StackPane ap;
public void ButtonClicked(ActionEvent e) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("PitchRecognition.fxml"));
Parent root = (Parent)loader.load();
Stage stage = (Stage) ap.getScene().getWindow();
stage.hide();
Stage newStage = new Stage();
Scene scene = new Scene(root);
newStage.setScene(scene);
newStage.setMaximized(true);
newStage.show();
}
}

How to Achieve One Menubar for more then one scenes in javaFx

I am basically new to Java FX 2.
Scenario:
I have 3 Scenes and I want a way to add menu-bar such that I don't i don't want to explicitly remove the menu bar from previous scene and add it to new one. Like Some thing a Parent Scene or some way menu-bar is attached to Stage. I mean menu-bar is added just one time and always be present whatever scene is in front or not.
If This is Possible How Can I do this.
Here is the Default Example Provided by Oracle Docs of JavaFX http://docs.oracle.com/javafx/2/ui_controls/MenuSample.java.html
public class Main extends Application {
final ImageView pic = new ImageView();
final Label name = new Label();
final Label binName = new Label();
final Label description = new Label();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
stage.setTitle("Menu Sample");
Scene scene = new Scene(new VBox(), 400, 350);
scene.setFill(Color.OLDLACE);
MenuBar menuBar = new MenuBar();
// --- Graphical elements
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.setPadding(new Insets(0, 10, 0, 10));
makeContentsForVBox();// in this vBox area will be fill with name pic desrciption
vbox.getChildren().addAll(name, binName, pic, description); // name is lable
// --- Menu File
Menu menuFile = new Menu("File");
MenuItem add = new MenuItem("Shuffle",
new ImageView(new Image(getClass().getResourceAsStream("new.png"))));
add.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
shuffle();
vbox.setVisible(true);
}
});
MenuItem clear = new MenuItem("Clear");
clear.setAccelerator(KeyCombination.keyCombination("Ctrl+X"));
clear.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
vbox.setVisible(false);
}
});
MenuItem exit = new MenuItem("Exit");
exit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
System.exit(0);
}
});
menuFile.getItems().addAll(add, clear, new SeparatorMenuItem(), exit);
((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
stage.setScene(scene);
stage.show();
}
}
So Here menuBar is added to a scene. if i swap the scene and bring an other scene in front ... What will i do. i think I remove menuBar from this scene and add to other or simply add to new one. so every time i have to do this when i change. Is there any way to avoid this??
The approach I would prefer is to use a Scene with BorderPane as its root
scene.setRoot(borderPane);
You can add the MenuBar to the top of the BorderPane and at its Center you can place SplitPane
BorderPane borderPane = new BorderPane();
borderPane.setTop(menuBar);
borderPane.setCenter(splitPane);
Whenever you need to switch to WebView just replace it with SplitPane :
borderPane.setCenter(webView);
Following this approach, your MenuBar will always remain on TOP and you can switch between SplitPane and WebView

Categories

Resources