Updating GUI instead of new scene - java

I currently have
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
String dd = "Hello";
stage.setTitle("Greetings"); //creates title
button_roll = new Button("Roll");
StackPane layout1 = new StackPane();
layout1.getChildren().add(button_roll);
Scene scene1 = new Scene(layout1, 600, 600);
stage.setScene(scene1);
Label mylab = new Label();
mylab.setText(dd);
Scene scene2 = new Scene(mylab, 600, 600);
button_roll.setOnAction(e -> stage.setScene(scene2));
stage.show();
}
My code currently displays "Hello" into the scene as a new scene.
I was wondering if there was a way to just update the scene1 to display the text instead of creating a whole new scene with just the text in it.
Is there terminology for what I want to do, if so what is it?
Any help would be great!

Your problem is you never add the Label to the Scene. Having the root node as StackPane will stack the Label and Button over each other. You need to replace StackPane with VBox, HBox, or a more suitable Node. Comments in the code.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application
{
#Override
public void start(Stage stage) throws Exception
{
String helloString = "Hello";//String use in the lable once the button is pressed.
Label lblHello = new Label();//Label that will show helloString once the button is pressed.
Button btnRoll = new Button("Roll");//The button that will trigger the action to change the label from empty string to helloString.
btnRoll.setOnAction((t) -> {//Set the button's action
lblHello.setText(helloString);//set the label's text to helloString.
});
VBox vbLayoutRoot = new VBox(lblHello, btnRoll);//The root layout is a VBox. Add the label and the btn to the root layout.
Scene scene = new Scene(vbLayoutRoot, 600, 600);//Add the root layout to the scene.
stage.setScene(scene);//Set the scene.
stage.setTitle("Greetings"); //creates title
stage.show();//Show the stage.
}
public static void main(String[] args)
{
launch(args);
}
}

I am not familiar with javaFX, but maybe you should try an EventHandler/ActionEvent:
button_roll.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
mylab.setText("Hello");
}
});

You should do like this:-
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
String dd = "Hello";
stage.setTitle("Greetings"); //creates title
Button button_roll = new Button("Roll");
StackPane layout1 = new StackPane();
layout1.getChildren().add(button_roll);
Scene scene1 = new Scene(layout1, 600, 600);
stage.setScene(scene1);
Label mylab = new Label();
mylab.setText(dd);
button_roll.setOnAction(e -> {
layout1.getChildren().clear();
layout1.getChildren().add(mylab);
});
stage.show();
}

Related

JavaFX wait until value is set

I am struggling with the following problem:
I have something like a popup in my javafx application, that should block the application, until the user made some input. It is NOT a seperate stage, where i can call showAndWait() and then return the input of the stage. The popup is realized as a pane, that is placed over the other components. And now i do something like this:
PopupPane pp = new PopupPane()
stackPane.add(new PopupPane()); //show pane
//... waiting until user terminates popup
return pp.getInput(); //returns input when user terminates popup
So i want pp.getInput() to wait, until the user presses the OK/CANCEL/APPLY/... button in my popup. How can i realize something like showAndWait() in this situation?
One possible way to do this would be to utilize an additional pane that can be disabled while the "popup" is being displayed.
For example, say the root layout pane of your Scene is a StackPane. You could wrap all the rest of your interface in another Pane that you'll disable or enable as needed.
When the "popup" needs to be displayed, add it to your StackPane and disable the "content" pane. When the popup closes, just remove it from your StackPane and re-enable the "content" pane.
Here's a quick and admittedly unattractive example of the concept:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SimulatedPopupExample extends Application {
private static StackPane root;
private static BorderPane content;
public static void main(String[] args) {
launch(args);
}
private static void showPopup() {
// Disable the main layout pain
content.setDisable(true);
VBox popup = new VBox();
popup.setPadding(new Insets(10));
popup.setAlignment(Pos.CENTER);
popup.setStyle("-fx-border-color: black; -fx-background-color: -fx-base;");
popup.setMaxSize(200, 200);
popup.getChildren().add(
new Button("Close Popup") {{
setOnAction(event -> {
// Re-enable the pane
content.setDisable(false);
// Remove popup from root layout
root.getChildren().remove(popup);
});
}}
);
// Add popup to root layout
root.getChildren().add(popup);
}
#Override
public void start(Stage primaryStage) {
// Simple Interface
root = new StackPane();
content = new BorderPane(
new Button("Show \"Popup\"") {{
setOnAction(e -> showPopup());
}},
new Button("Top Button"),
new Button("Right Button"),
new Button("Bottom Button"),
new Button("Left Button")
);
root.getChildren().add(content);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setWidth(500);
primaryStage.setHeight(400);
primaryStage.setTitle("SimulatedPopupExample Sample");
primaryStage.show();
}
}
The Result:
Here is a Custom Dialog that can not be closed or accepted until the user enter data in the TextField
private void showInputTextDialog(){
Label lblAmt = new Label("Enter Amount");
Button btnOK = new Button("OK");
TextField txtAmt = new TextField();
AnchorPane customDialog = new AnchorPane();
customDialog.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
customDialog.getChildren().addAll(lblAmt,btnOK,txtAmt);
lblAmt.setLayoutX(30);
lblAmt.setLayoutY(30);
txtAmt.setLayoutX(164);
txtAmt.setLayoutY(25);
txtAmt.setMaxWidth(116);
btnOK.setLayoutX(190);
btnOK.setLayoutY(100);
btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
Scene secondScene = new Scene(customDialog, 300, 180);
EventHandler<ActionEvent> filter = event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
};
// New window (Stage)
Stage newWindow = new Stage();
//newWindow.initStyle(StageStyle.UNDECORATED);
newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setResizable(false);
//newWindow.setTitle("Custom Dialog");
newWindow.setScene(secondScene);
btnOK.addEventHandler(ActionEvent.ACTION,filter);
btnOK.setOnAction(evt -> {
String str = txtAmt.getText();
System.out.println("################ str "+str);
if(txtAmt.getText().trim().equals("")) {
evt.consume();
txtAmt.clear();
txtAmt.requestFocus();
}else{
txAMT = Double.valueOf(str);
newWindow.close();
}
});
newWindow.setOnCloseRequest(event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
});
txtAmt.requestFocus();
newWindow.showAndWait();
}

Application with BorderPane doesn't display simple button

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);.

How to change CenterPane from LeftPane in javaFx borderPane?

I am trying to make a panel in javafx and i used to a border pane as a main scene. There are 4 windows (main1, main2, main3,main4) for center panel, and there is a navigation menu in left panel.
borderPane.setCenter(mainMenu1.getCenterMain1UI());
//borderPane.setCenter(mainMenu2.getCenterMain2UI());
//borderPane.setCenter(mainMenu3.getCenterMain3UI());
//borderPane.setCenter(mainMenu4.getCenterMain4UI());
public BorderPane getAppWindow(){
if (borderPane == null){
borderPane = new BorderPane();
borderPane.setTop(topPanel.getTopPanelUI());
borderPane.setBottom(bottomPanel.getBottomPanelUI());
borderPane.setLeft(leftPanel.getLeftPanelUI());
borderPane.setCenter(mainMenu.getCenterMainUI());
borderPane.setAlignment(borderPane.getCenter(), Pos.TOP_LEFT);
}
return borderPane;
}
in the left panel controller
public class LeftPanelController {
public VBox leftPanelPane;
public Button btnLeftPanelMainmenu;
public Button btnLeftPanelDb;
public Button btnLeftPanelOfficeInfo;
public Button btnLeftPanelConfiguration;
public void btnLeftPanelMainmenuOnClickAction(ActionEvent e){
change border pane center to main
}
public void btnLeftPanelDbOnClickAction(ActionEvent e){
change border pane center to DB
}
public void btnLeftPanelOfficeInfoOnClickAction(ActionEvent e){
change border pane center to DB
}
public void btnLeftPanelConfigurationOnClickAction(ActionEvent e){
change border pane center to configuration
}
}
You'll need to set the on action event for each of your menu buttons so that it changes what is displayed in the center of the BorderPane.
Here's an example:
import java.util.LinkedHashMap;
import java.util.Map;
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.*;
import javafx.stage.Stage;
public class BorderPaneExample extends Application {
private Map<String, Node> menuOptions;
private Node defaultCenterNode = new Label("Example node 1");
#Override
public void start(Stage primaryStage) throws Exception {
menuOptions = new LinkedHashMap<>();
menuOptions.put("Main Menu", defaultCenterNode);
menuOptions.put("History", new Label("Example node 2"));
menuOptions.put("Office Info", new Label("Example node 3"));
menuOptions.put("Configuration", new Label("Example node 4"));
BorderPane root = new BorderPane();
root.setCenter(defaultCenterNode);
VBox menuLayout = new VBox();
for (String key : menuOptions.keySet()) {
Button button = new Button(key);
button.setMaxWidth(Double.MAX_VALUE);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.setCenter(menuOptions.get(key));
}
});
menuLayout.getChildren().add(button);
}
root.setLeft(menuLayout);
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.setTitle("BorderPane Example");
primaryStage.setResizable(false);
primaryStage.sizeToScene();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I changed my button click methods in the left panel like that;
public void btnLeftPanelMainmenuOnClickAction(ActionEvent e) {
AppWindow.borderPane.setCenter(AppWindow.mainMenu.getCenterMainUI());
}
public void btnLeftPanelDbOnClickAction(ActionEvent e) {
AppWindow.borderPane.setCenter(AppWindow.dbMenu.getCenterDbUI());
}
public void btnLeftPanelConfigurationOnClickAction(ActionEvent e) {
AppWindow.borderPane.setCenter(AppWindow.configMenu.getCenterConfigurationUI());
}

Switching scenes don't retain maximized screen in JavaFX

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);
}
}

JavaFX switch scene in Fullscreen

I want to switch the scenes of my JavaFX application in Fullscreen with a "Next"-Button. But if I click on that Button it switches from fullscreen to windowed and back to fullscreen within a second. How can I achieve to avoid that and stay in fullscreen mode?
Some relevant snippets:
Application.java:
public class Application extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLMain.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
stage.setFullScreen(true);
stage.setTitle("AppName");
}
public static void main(String[] args) {
launch(args);
}
}
FXMLMainController.java:
#FXML
private void handleBtnNext(ActionEvent event) throws Exception{
Stage stage;
Parent root;
if(event.getSource()==btnNext){
//get reference to the button's stage
stage=(Stage) btnNext.getScene().getWindow();
//load up OTHER FXML document
root = FXMLLoader.load(getClass().getResource("FXMLOptions.fxml"));
}
else{
stage=(Stage) btnNext.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXMLMain.fxml"));
}
//create a new scene with root and set the stage
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
stage.setFullScreen(true);
}
That behavior, where the app pops out of full screen mode when you switch scenes, is weird (it happens for me too on Java 8u60, OS X 10.11.3). It may be a bug.
To work-around it, you can just reuse the same stage and scene and adjust the root of your scene, rather than changing the scene itself.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FullScreenScenes extends Application {
#Override
public void start(Stage stage) throws Exception {
Button next1 = new Button("Show Scene 2");
StackPane layout1 = new StackPane(next1);
layout1.setStyle("-fx-background-color: palegreen;");
Button next2 = new Button("Show Scene 1");
StackPane layout2 = new StackPane(next2);
layout2.setStyle("-fx-background-color: paleturquoise;");
Scene scene = new Scene(layout1);
next1.setOnAction(event -> scene.setRoot(layout2));
next2.setOnAction(event -> scene.setRoot(layout1));
stage.setScene(scene);
stage.setFullScreen(true);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
first Adjust your scene Builder view (Responsive responsive screen sizes) this is your Scene Builder View problem Adjust the view (Layout or Fxid ) check again .

Categories