I currently use the following code to switch between scenes. I want to switch between windows and KEEP the window size (so when the users change the windows size manually by resizing the window, it will stay at the chosen size even after scene change).
Scene scene = new Scene(pane); // new Scene(pane, userChosenWidth??, userChosenHeight??);
stage.setScene(scene);
stage.sizeToScene();
Does anyone know how to accomplish this?
Just call getWidth() and getHeight() on the current Scene. If you don't have a reference to the current scene, you can get one with stage.getScene().
Setting width and height in Stage worked for me.
double prevWidth = stage.getWidth();
double prevHeight = stage.getHeight();
stage.setScene(scene);
stage.setHeight(prevHeight);
stage.setWidth(prevWidth);
I created this class:
public class AppSize {
private static final String HEIGHT = "Height";
private static final String WIDTH = "Width";
private static final String Y = "Y";
private static final String X = "X";
private final static Preferences prefs = Preferences.userNodeForPackage(AppSize.class);
public static void setSize(Stage stage) {
Optional.ofNullable(prefs.getDouble(X, -1)).filter(x->x>=0).ifPresent(stage::setX);
Optional.ofNullable(prefs.getDouble(Y, -1)).filter(y->y>=0).ifPresent(stage::setY);
Optional.ofNullable(prefs.getDouble(WIDTH, -1)).filter(width->width>=0).ifPresent(stage::setWidth);
Optional.ofNullable(prefs.getDouble(HEIGHT, -1)).filter(height->height>=0).ifPresent(stage::setHeight);
stage.setOnCloseRequest(
e->{
if(stage.isFullScreen()) {
return;
}
prefs.putDouble(X, stage.getX());
prefs.putDouble(Y, stage.getY());
prefs.putDouble(WIDTH, stage.getWidth());
prefs.putDouble(HEIGHT, stage.getHeight());
});
}
}
its use:
public class App extends Application {
#Override
public void start(Stage stage) {
var label = new Label("AppSize test.");
var scene = new Scene(new StackPane(label), 640, 480);
stage.setScene(scene);
AppSize.setSize(stage);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Related
Please, consider the following code:
public class JavaFxTest4 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button button = new Button();
button.setText("dialog");
button.setOnAction((e) -> {
Dialog<?> d = new Dialog<>();
final Window window = d.getDialogPane().getScene().getWindow();
Stage stage = (Stage) window;
stage.setMinHeight(450);
stage.setMaxHeight(450);
stage.setHeight(450);
stage.setMinWidth(600);
stage.setMaxWidth(600);
stage.setWidth(600);
window.setY(300); //<---- note this line
window.setX(660); //<---- note this line
d.showAndWait();
});
VBox root = new VBox();
root.getChildren().addAll(button);
var scene = new Scene(root, 1920, 1000);
primaryStage.setScene(scene);
primaryStage.show();
}
}
As you can see window position is 660 (x) and 300 (y). And this is the result:
As you can see x position is correct, but y position is not. Is this a bug or I misunderstand something? I use javafx 19-ea+3 and openjdk version "14.0.2" on Ubuntu 20.
It is a bug in JavaFX. Issue is here
This question already has answers here:
MenuBar changes the background color of the scene (Java FX 8)
(1 answer)
JavaFX: Just Declaring Nodes changes Background of other Nodes
(1 answer)
Closed 1 year ago.
I created JavaFX application, made whole screen black. Then I decided to add new instance of TextField to get input from user, but noticed that whole screen now is white-ish. I didn't even added it to any pane or scene. I tried to change TextField's background color to empty, but nothing removes white-ish color.
Here is code, that makes black window:
package org.medianik.tictactoe;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import java.io.InputStream;
import static org.medianik.tictactoe.util.Constants.*;
/**
* JavaFX App
*/
public class TicTacToe extends Application{
private static TicTacToe instance;
public static TicTacToe getInstance(){
return instance;
}
private final int width;
private final int height;
final Pane pane;
public TicTacToe(){
width = calculateWidth();
height = calculateHeight();
pane = new StackPane();
instance = this;
}
public static void main(String[] args){
launch();
}
/**
* The entry point
*/
#Override
public void start(Stage stage){
//In Constants.java:
//public static final Color BACKGROUND_COLOR = Color.BLACK;
var scene = new Scene(pane, width, height, BACKGROUND_COLOR);
stage.setScene(scene);
stage.show();
setupIcon(stage);
// new TextField();
}
private int calculateWidth(){
var bounds = Screen.getPrimary().getBounds();
return Math.min((int) bounds.getWidth() - GLOBAL_OFFSET, MAX_WIDTH);
}
private int calculateHeight(){
var bounds = Screen.getPrimary().getBounds();
return Math.min((int) bounds.getHeight() - GLOBAL_OFFSET, MAX_HEIGHT);
}
private void setupIcon(Stage stage){
InputStream inputIcon = getClass().getResourceAsStream("/icon.png");
Image icon = new Image(inputIcon);
stage.getIcons().add(icon);
}
#Override
public void stop() throws Exception{
System.out.println("stop");
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}
And here is window:
Picture of ordinary person
But if I uncomment one single line:
/**
* The entry point
*/
#Override
public void start(Stage stage){
//In Constants.java:
//public static final Color BACKGROUND_COLOR = Color.BLACK;
var scene = new Scene(pane, width, height, BACKGROUND_COLOR);
stage.setScene(scene);
stage.show();
setupIcon(stage);
new TextField();
}
Everything goes white-ish:
Picture of insane one
Even if I make background empty nothing changes:
/**
* The entry point
*/
#Override
public void start(Stage stage){
var scene = new Scene(pane, width, height, BACKGROUND_COLOR);
stage.setScene(scene);
stage.show();
setupIcon(stage);
TextField text = new TextField();
text.setBackground(Background.EMPTY);
}
What should I do to fix this?
Was a bit astonished to see this (and had no immediate answer ;) so did a bit of digging:
verified that I can reproduce the different behavior in the (slightly stripped-down) example
added debug print outs of pane's state before/after creating the TextField: noted that its background is null before and not-null after
followed field creation in a debugger: noted styleSheet init on classLoading of Control
So the reason for the difference is that the default styleSheet is loaded in static code block of class Control (there might be other paths):
static {
...
// Ensures that the default application user agent stylesheet is loaded
if (Application.getUserAgentStylesheet() == null) {
PlatformImpl.setDefaultPlatformUserAgentStylesheet();
}
}
Modified example:
public class TicTacToe extends Application{
public static void main(String[] args){
launch();
}
#Override
public void start(Stage stage){
Pane pane = new StackPane();
var scene = new Scene(pane, 500, 300, Color.BLACK);
stage.setScene(scene);
stage.show();
System.out.println("pane before styling: " + pane.getBackground());
new TextField();
Platform.runLater(() -> {
System.out.println("pane after styling: " + pane.getBackground());
});
}
}
I want to create a simple poke where I have a splash screen (like an adobe one) that leads to a multi screen application.
To do so here's my main class ScreensFramework :
public class ScreensFramework extends Application {
public static String screen1ID = "main";
public static String screen1File = "Screen1.fxml";
public static String screen2ID = "screen2";
public static String screen2File = "Screen2.fxml";
public static String screen3ID = "screen3";
public static String screen3File = "Screen3.fxml";
private Pane splashLayout;
private Stage mainStage;
#Override
public void init() {
ImageView splash = new ImageView(new Image("http://www.versluis.com/wp-content/uploads/2013/08/CCsplash-610x520.png"));
splashLayout = new VBox();
splashLayout.getChildren().addAll(splash);
splashLayout.setEffect(new DropShadow());
}
#Override
public void start(Stage primaryStage) {
showSplash(primaryStage);
Timeline timeline = new Timeline(new KeyFrame(
Duration.millis(2500),
ae -> showMainStage(primaryStage)));
timeline.play();
}
private void showMainStage(Stage initStage) {
initStage.hide();
mainStage = new Stage(StageStyle.DECORATED);
mainStage.setTitle("My Test");
mainStage.setIconified(true);
ScreensController mainContainer = new ScreensController();
mainContainer.loadScreen(ScreensFramework.screen1ID, ScreensFramework.screen1File);
mainContainer.loadScreen(ScreensFramework.screen2ID, ScreensFramework.screen2File);
mainContainer.loadScreen(ScreensFramework.screen3ID, ScreensFramework.screen3File);
mainContainer.setScreen(ScreensFramework.screen1ID);
Group root = new Group();
root.getChildren().addAll(mainContainer);
Scene scene = new Scene(root);
mainStage.setScene(scene);
mainStage.show();
mainStage.toFront();
}
private void showSplash(Stage initStage) {
Scene splashScene = new Scene(splashLayout);
initStage.initStyle(StageStyle.UNDECORATED);
initStage.initStyle(StageStyle.TRANSPARENT);
splashScene.setFill(Color.TRANSPARENT);
initStage.setScene(splashScene);
initStage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Things are working pretty fine, except for one thing :
mainStage.toFront();
When this is called, my icon flash in orange but the window does not come in front. So basically I have my splash screen and then nothing if I don't click my self on the windows icon.
Where does it come from ?
I have strange problems with JavaFX that look a lot like a bug. I want to do the following:
Entering fullscren when starting my application
Press escape to exit the application (not fullscreen, the entire application)
So far, I have the following code:
public class AppTest extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
stage.setOnCloseRequest(t -> {
Platform.exit();
System.exit(0);
});
stage.setFullScreenExitHint("Press ESCAPE to exit");
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
stage.setFullScreen(true);
Rectangle2D screenBounds = Screen.getPrimary().getBounds();
stage.setX(screenBounds.getMinX());
stage.setY(screenBounds.getMinY());
double screenWidth = screenBounds.getWidth();
double screenHeight = screenBounds.getHeight();
stage.setWidth(screenWidth);
stage.setHeight(screenHeight);
Group root = new Group();
Scene scene = new Scene(root);
stage.setScene(scene);
scene.setOnKeyTyped(event -> {
if(event.getCode() == KeyCode.ESCAPE) {
stage.close();
}
});
Canvas canvas = new Canvas(screenWidth, screenHeight);
root.getChildren().add(canvas);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLUE);
gc.fillRect(0,0, screenWidth, screenHeight);
stage.show();
}
}
I'm on macOS.
In general it goes fullscreen. I'm saying in general because the real version of this code doesn't always. Sometimes, it is just a maximized window.
Then, when pressing escape, I get a maximized window instead of exiting the application.
How can I fix that?
Change:
scene.setOnKeyTyped
To:
scene.setOnKeyReleased
This explains why.
I am working on a project and I need you help.
I want to know that is this possible to set anchorpane constraints in percentage as something like
AnchorPane.setLeftAnchor(content1, 35%);
Yes it can be by updating constraint values on every scene size change:
public class AnchorDemo extends Application {
private final Button button = new Button("Add");
private final ListView list = new ListView();
#Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
AnchorPane.setTopAnchor(list, 10.0);
AnchorPane.setLeftAnchor(list, 10.0);
AnchorPane.setTopAnchor(button, 10.0);
AnchorPane.setRightAnchor(button, 10.0);
root.getChildren().addAll(list, button);
Scene scene = new Scene(root, 300, 250);
scene.widthProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
updateWidthConstaints(newValue.doubleValue());
}
});
primaryStage.setScene(scene);
primaryStage.show();
updateWidthConstaints(scene.getWidth());
}
private void updateWidthConstaints(double width) {
// roughly give to the list 66% while to the button 33% of available
// space, besides paddings.
// +5s are for extra padding
AnchorPane.setRightAnchor(list, width * 1 / 3 + 5);
AnchorPane.setLeftAnchor(button, width * 2 / 3 + 5);
}
public static void main(String[] args) {
launch(args);
}
}