How to set window size on runtime? - java

I'm developing a JavaFX FXML application. I need to resize the window from the controller class at runtime.
I found out that its possible to do this from the application class by setting maxHeight and maxWidth properties of the stage. But how to do it from the controller class while the application is running?

Define a button in the controller class and set on action of it like
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
// OR, if you define btn as #FXML private Button btn.
Stage stage = (Stage) btn.getScene().getWindow();
// these two of them return the same stage
stage.setWidth(new_val);
stage.setHeight(new_val);
}
});
where stage is your primary (main) stage.

Related

Switching between a JavaFX scene and a non-JavaFX scene

I've created a game and I wanted to add a start screen to it, I've added it using FXML as well as added 2 buttons (start and quit).
Upon pressing the start button, I want the game to load and switch scenes to the start of the game. I've got a rough idea of how to do it but i'm struggling a bit as my SampleController class does not know anything about starting up the game etc, as all of that code (as well as the code to load up the initial start menu) is in my Main class, so this is the kind of thing I tried:
#FXML
void startGame(ActionEvent event) {
background.start();
primaryStage.setScene(scene);
start();
}
I tried doing it using a function to switch scenes and it didn't work, also tried to get the information about the stage using Stage window = (Stage)((Node)event.getSource()).getScene().getWindow(); as I saw it as a possible solution from a YouTube video however it was telling me that Node cannot be resolved to a type.
This is my code:
Main
public class Main extends Application
{
AnimationTimer timer;
MyStage background;
Animal animal; //This is the player/frog that is moved
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/startMenu.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Game");
primaryStage.show();
//All the code after this point is essentially what I want to be executed upon pressing the button
background = new MyStage();
Scene scene = new Scene(background,600,800);
BackgroundImage froggerback = new BackgroundImage("file:resources/froggerBackground.png");
background.add(froggerback);
//At this point, a bunch of code like the line below is called to add in the different obstacles to the background
background.add(new Turtle(500, 376, -1, 130, 130));
//background.start();
//primaryStage.setScene(scene);
//primaryStage.show();
//start();
}
SampleControllerClass
public class SampleController {
#FXML
private Button quitButton;
#FXML
private Button startButton;
#FXML
void startGame(ActionEvent event) {
}
#FXML
void quitGame(ActionEvent event) {
}
Appreciate any help.
Thanks.
Assuming:
Your SampleController is the FXML controller which links the startButton for a game.
In your SampleController, you have an action event handler defined for your start button startGame.
You have another FXML file defined for your game layout, called game.fxml.
Then, you can get the current scene from the start button and replace the root of the scene with the new parent derived when loading the game.fxml:
#FXML
private Button startButton;
#FXML
void startGame(ActionEvent event) {
Parent gameRoot = FXMLLoader.load(
getClass().getResource("game.fxml")
);
startButton.getScene().setRoot(gameRoot);
}
You don't need to create a new scene or stage (unless that is something you really want to do for some other reason). If you really need to do that (which you probably don't), then that is outside the scope of what I am supplying in this answer.

How do I change the color of an anchorpane from the controller class?

For a GUI I'm making the minimize, maximize, close buttons similar to that of Spotify by using an anchorpane for each 'button'. I created the buttons via scenebuilder and they are loaded to the class via fxml. I can't figure out how to call a particular instance of an anchorpane in the controller class to change its background color when the mouse enters or exits.
public static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 1280, 800));
...
this.primaryStage = primaryStage;
etc.
is how the UI class is set up
I expect the color of the anchorpane to change when the mouse enters the bounds, but as of now I have no idea how to call it.
Solved it, had to set an fxid to the anchorpane and then initiate it in the controller class after an #FXML.
Kinda like this:
#FXML
Anchorpane someButton;
#FXML
public void makeButtonWhite(MouseEvent event)
{
someButton.setStyle("-fx-background-color: #ffffff");
}
The most convenient way of doing this imho is using a stylesheet to assign the background.
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" stylesheets="#style.css">
<children>
<AnchorPane prefWidth="30" prefHeight="20" styleClass="my-button"/>
</children>
</AnchorPane>
style.css (same directory as fxml)
/* default style */
.my-button {
-fx-background-color: blue;
}
/* style when mouse is inside the region */
.my-button:hover {
-fx-background-color: red;
}
This allows you to easily add the style to multiple Regions; you simply need to add the style class it (styleClass="my-button").
the code you need for starting this must be the starting class
public class Class extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(this.getClass().getResource("/Folder/File.fxml"));
loader.setController(yourControllerClass());
//only if you do something with the controller class afterwards
YourControllerClass controller = loader.setController();
Parent parent = loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
you know the code method in scenebuilder there you can set on mouse entered and exited for a button, a label etc. then if for example the button with the id "closeButton" and the OnMouseEntered "closeButtonOnEntered" and the OnMouseExited "closeButtonOnExited"
this will be the code you need
public yourcontrollerclass {
#FXML
Button closeButton;
#FXML
private void closeButtonOnEntered() {
//sets button red
button.setStyle("-fx-background-color: #ff0000");
}
#FXML
private void closeButtonOnExited() {
//sets button your first color
button.setStyle("-fx-background-color: transparent");
}
}
this can be done with nearly every thing in sceneBuilder
I hope i could help you(sorry for my bad english)

JavaFX BorderPane inside an AnchorPane?

I'm currently trying to show a BorderPane inside my AnchorPane (that is also inside my StackPane). I tried to show a new Scene but it show me 2 items in my Windows taskbar, and this is not really what I want.
For exemple, when you open the Preference in Eclipse, u get another window that is not visible in the taskbar.
So basically, the only thing I need is a window that looks like an ImageView, like anchored in the AnchorPane , not resizable and undecorated.
Expected result at end
This is what I tried:
btnDice.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0) {
Scene newScene = new Scene(new BorderPane(), 230, 100);
Stage newWindow = new Stage();
newWindow.setScene(newScene);
newWindow.show();
}
});

JavaFX - How to change scene using a scene from another class?

I have the following class which has a button.
public class GUI extends Application {
private BorderPane mainLayout = new BorderPane();
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Main Menu");
FlowPane layout = new FlowPane();
Button button = new Button("Click");
layout.getChildren().addAll(button);
mainLayout.setTop(layout);
Scene scene = new Scene(mainLayout, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
If I have another class with a scene, how can I update the GUI class to show the scene by pressing the button?
The preferred mechanism would probably be to get the stage dynamically from a trigger event, for example:
button.setOnAction(event -> {
Scene newScene = // ... commands which define the new scene.
Stage stage = ((Node) event.getTarget()).getScene().getStage();
// or alternatively, just:
// Stage stage = button.getScene().getStage();
stage.setScene(newScene);
});
An alternative is to provide a static accessor to the main stage in the Application.
Change your GUI class to add an accessor for the stage:
public class GUI extends Application {
private static Stage guiStage;
public static Stage getStage() {
return guiStage;
}
#Override
public void start(Stage primaryStage) {
guiStage = primaryStage;
// other app initialization logic . . .
}
}
In your class which needs to change the scene for the GUI stage to a new scene, invoke:
Scene newScene = // ... commands which define the new scene.
GUI.getStage().setScene(newScene);
Using a static accessor in this specific instance is generally OK, because you can only have a single Application instance launched for a given JVM execution. The only real drawback is that you have a coded dependency between the class creating your new scene and your Application class. But, for some application types, this won't matter.

Cannot Maximize Window with JavaFX

I made a custom Minimize button this way:
public MinimizeButton() {
Button button = new Button("-");
button.getStyleClass().clear();
button.getStyleClass().add("actionbutton");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Stage stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
stage.setIconified(true);
}
});
this.getChildren().add(button);
}
And I obviously called
primaryStage.initStyle(StageStyle.UNDECORATED);
The button is working well.
The issue is that when I try to maximize the Window once the Stage is iconified, it takes a couple of seconds for the Window to redraw the Stage.
Any ideas on how to make the "Maximizing process" of the Window faster?
Fixed it by using
primaryStage.initStyle(StageStyle.TRANSPARENT);
instead of
primaryStage.initStyle(StageStyle.UNDECORATED);

Categories