very new to JavaFX I'm following a simple tutorial here
I created a new JavaFX project but it has a BorderPane as a default rather than a StackPane as the tutorial says, so I left it there.
The application only has a button on it and if I use the BorderPane the button isn't displayed.
If I change it to StackPane the button shows up.
Thinking that for some reason the BorderPane was clipping something off, I made the application windows full size, but I still couldn't see the button.
Here is the code with the BorderPane the one that doesn't display the button:
package application;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("This is a test!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Any idea?
Take a look at the docs about BorderPane:
BorderPane lays out children in top, left, right, bottom, and center
positions.
Therefore you need to use stuff like:
borderPane.setTop(toolbar);
borderPane.setCenter(appContent);
borderPane.setBottom(statusbar);
In your case root.getChildren().add(btn); should be for example root.setCenter(btn);.
Related
I want somehow to make the button change his position randomly when i push the button. I've got one idea how to solve this problem, one of them i've highlighted below, but i already think that this is not what i need.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Ulesanne6 extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Test");
Button btn = new Button();
btn.setText("Hello");
btn.setOnAction(new EventHandler <javafx.event.ActionEvent>() {
#Override
public void handle(javafx.event.ActionEvent event) {
//btn.setLayoutY(Math.random());
//btn.setLayoutX(Math.random());
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
}
I think that somewhere here i suppose to do that, but i don't know how... yet.
public void handle(javafx.event.ActionEvent event) {
//btn.setLayoutY(Math.random());
//btn.setLayoutX(Math.random());
}
How about this?
public void handle(javafx.event.ActionEvent event) {
btn.setTranslateX(ThreadLocalRandom.current().nextDouble(800));
btn.setTranslateY(ThreadLocalRandom.current().nextDouble(600));
}
You might also want to make sure that the button is placed somewhere on the screen and not off the screen. So if you know the width and height of the button, take it into account.
public void handle(javafx.event.ActionEvent event) {
btn.setTranslateX(ThreadLocalRandom.current().nextDouble(800 - buttonWidth));
btn.setTranslateY(ThreadLocalRandom.current().nextDouble(600 - buttonHeight));
}
EDIT: Please note that you are using a StackPane as your root parent. StackPane likes to position its children based on alignment attribute of the StackPane. As such, for my answer to work correctly, you must make your root parent a Group instead of a StackPane. A regular Pane can also work.
Group root = new Group();
How to apply StageStyle.utility and StageStyle.undecorated to the same stage.
I am using this for the internal window/ popup.
Or if I have to follow any other solution please do stuggest.
Thanks
Your problem :
Application two styles StageStyle.UTILITYand StageStyle.UNDECORATED for the same stage.
Because
you asked for suggestion
to solve your problem.
Suggestion :
I suggest to use in-sideFX/Undecorator
(Downlaod the jar file and add it into your project) then we will make some modifications to keep your need ,I tried to create this sample of code for creating a Popup window inside parent window (Owner window) :
package javafxpopup;
import insidefx.undecorator.Undecorator;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
/**
*
* #author Menai Ala Eddine
*/
public class Undecorated extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Click");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Stage popStage = new Stage();
popStage.initStyle(StageStyle.TRANSPARENT);
StackPane root = new StackPane();
root.getChildren().add(new Label("I'm popup window"));
applyModification(popStage, root);
popStage.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root,500,500));
primaryStage.setTitle("Hello World!");
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private void applyModification(Stage primaryStage, StackPane root) {
Undecorator undecorator = new Undecorator(primaryStage, root);
undecorator.getStylesheets().add("/skin/undecorator.css");
Scene scene = new Scene(undecorator, 300, 250);
primaryStage.setScene(scene);
scene.setFill(null);
Node stageMenu = undecorator.lookup("#StageMenu");
stageMenu.setVisible(false);
Node maximize = undecorator.lookup(".decoration-button-maximize");
maximize.setVisible(false);
Node manimize = undecorator.lookup(".decoration-button-minimize");
manimize.setVisible(false);
Node restore = undecorator.lookup(".decoration-button-fullscreen");
restore.setVisible(false);
}
}
By clicking the button the pop window will showing into owner window :
As you see StageStyle.UNDECORATED and StageStyle.UTILITY in the same time.
PS: it is a suggestion you can find many solutions.
So I am trying to learn Java now that I know JavaScript and PHP. I am working in Netbeans with JavaFX and I am trying to create a program that creates 5 buttons. (This is modifying the code that comes with Netbeans when creating a new JavaFX Application.) If I change the y-argument of the scene to be less than the y of all of the buttons, it will not display the remaining buttons and it will not be able scroll down. This is what I have so far. How do I enable it to scroll down so all buttons can be seen? I know that I can just change the scene back to its old height but I want to learn about scrolling with JavaFX.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javax.swing.JScrollPane;
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
Button[] btn=new Button[5];
for(int i=0;i<5;i++){
btn[i] = new Button();
btn[i].setText(i+"");
GridPane.setRowIndex(btn[i],i);
root.getChildren().addAll(btn[i]);
btn[i].setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("This is a button");
}
});
}
Scene scene = new Scene(root, 300, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Using ScrollPane to set root as:
ScrollPane sp = new ScrollPane();
sp.setContent(root);
Scene scene = new Scene(sp, 300, 50);
My configuration:
I need to switch between scenes via the same stage
I need to keep a maximized stage that fills the whole screen
My issue:
although I set my stage to be maximized primaryStage.setMaximized(true);it adopts its size to the size of the scenes afterwards.
What I tried until now:
I tried using primaryStage.getScene().setRoot(<the root node of scene>). While it worked to keep the stage maximized, yet after each change of scene the focus on the previously focused gui control is lost (after switch only the first gui control in the scene hierarchy is focused). I really need scenes, so that any gui control that was focused still be will focused after the stage changes its scene.
I need your assistance:
I really need your assistance in keeping the stage maximized during changing scenes.
Here is my example code:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first scene
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
Scene scene1 = new Scene(root1, 300, 250);
// second scene
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
Scene scene2 = new Scene(root2, 500, 400);
// button actions
btn1.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene2);
});
btn2.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene1);
});
primaryStage.setMaximized(true);
primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
SOLUTION
create scenes depending on the screen size of your monitor
after several attempts I finally figured how to easily solve this problem to keep the maximized screen while retaining the focused node on each Scene. Hope it helps the community:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
// get screensize of monitor
Rectangle2D screenSize = Screen.getPrimary().getVisualBounds();
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first rootNode
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
Scene scene1 = new Scene(root1, screenSize.getWidth(), screenSize.getHeight());
// second rootNode
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
Scene scene2 = new Scene(root2, screenSize.getWidth(), screenSize.getHeight());
// button actions
btn1.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene2);
});
btn2.setOnAction((ActionEvent event) -> {
primaryStage.setScene(scene1);
});
primaryStage.setMaximized(true); // keep this since otherwise the titlebar is bit overlapped
primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I think it's a bug. You can report it at: http://bugreport.java.com.
In the meantime, as a workaround, you probably need to just set the pane for a shared scene, replacing its content rather than replacing the scene.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class NewFXMainFixed extends Application {
#Override
public void start(Stage primaryStage) {
// init buttons
Button btn1 = new Button("switch to next scene >>");
Button btn2 = new Button("<< switch to previous scene");
// first scene
StackPane root1 = new StackPane();
root1.getChildren().add(btn1);
// second scene
StackPane root2 = new StackPane();
root2.getChildren().add(btn2);
// button actions
btn1.setOnAction((ActionEvent event) ->
primaryStage.getScene().setRoot(root2)
);
btn2.setOnAction((ActionEvent event) ->
primaryStage.getScene().setRoot(root1)
);
Scene scene = new Scene(root1);
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The thing that I am trying to here is to create a opaque button in StackPane within a transparent stage, but making the stage transparent will make all the contents transparent.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.*;
public class HelloWorld extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.initStyle(StageStyle.TRANSPARENT);
primaryStage.setOpacity(0.4);
primaryStage.setScene(scene);
primaryStage.show();
scene.getStylesheets().add("sample.css");
}
public static void main(String[] args) {
launch(args);
}
}
sample.css file contains
.button {
-fx-background-color: rgba(255,0,0,1);
}
Do this
btn.setStyle("-fx-background-color: any-non-transparent-color-you-wish;");
This will change the background of the button making it non transparent
just found out the answer. All I had to do was to change the fill colour to null on scene and change the css file.
scene.setFill(null);
css file
.root {
-fx-background-color: rgba(0,0,0,0.1);
}
.button {
-fx-background-color: rgba(255,0,0,1);
}