Comment centrer correctement une fenêtre dans Java FX?
Java FX fournit une fenêtre.centerOnScreen () pour - deviner quoi-centrer une fenêtre sur un écran. CEPENDANT, la définition de Java FX de "centre d'un écran" semble être à (0.5 x;0.33 y). J'espérais que c'était un bug, mais m'a dit que ce n'est pas.
De toute façon. Quelqu'un a-t-il trouvé une solution propre et facile sur la façon de centrer une fenêtre avant de l'afficher? Ma première approche conduit à le scintillement de l'écran, depuis la fenêtre doit être affichée en premier, avant d'être égocentrique.
public static void centerOnScreen(Stage stage) {
stage.centerOnScreen();
stage.setY(stage.getY() * 3f / 2f);
}
Mise à Jour: Ce que j'ai oublié de mentionner; Je ne connais pas la taille de la fenêtre à l'avance, donc pour la centrer manuellement, je dois d'abord l'afficher - ce qui la fait scintiller une fois. Je cherche donc une solution pour le centrer sans l'afficher d'abord - comme Java FX est capable de le faire, mais dans le mauvais sens.
4 answers
Voici comment vous le faites avant que la scène ne soit rendue visible:
double width = 640;
double height = 480;
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
stage.setX((screenBounds.getWidth() - width) / 2);
stage.setY((screenBounds.getHeight() - height) / 2);
final Scene scene = new Scene( new Group(), width, height);
stage.setScene(scene);
stage.show();
Et ceci après que la scène a été rendue visible, c'est-à-dire que vous pouvez utiliser les propriétés de la scène:
double width = 640;
double height = 480;
final Scene scene = new Scene( new Group(), width, height);
stage.setScene(scene);
stage.show();
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
stage.setX((screenBounds.getWidth() - stage.getWidth()) / 2);
stage.setY((screenBounds.getHeight() - stage.getHeight()) / 2);
Si vous avez plusieurs écrans, vous pouvez calculer la position manuellement en utilisant la liste des objets d'écran qui est renvoyée par l'écran .getScreens() méthode.
L'astuce générale pour répondre à l'initialisation d'une valeur est de créer un écouteur pour la propriété qui se supprime lorsque la propriété est initialisée. Donc, vous pouvez faire
Screen screen = Screen.getPrimary();
Rectangle2D sbounds = screen.getBounds();
double sw = sbounds.getWidth() ;
double sh = sbounds.getHeight();
listenToSizeInitialization(primaryStage.widthProperty(),
w -> primaryStage.setX(( sw - w) /2));
listenToSizeInitialization(primaryStage.heightProperty(),
h -> primaryStage.setY(( sh - h) /2));
primaryStage.show();
Avec
private void listenToSizeInitialization(ObservableDoubleValue size,
DoubleConsumer handler) {
ChangeListener<Number> listener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> obs,
Number oldSize, Number newSize) {
if (newSize.doubleValue() != Double.NaN) {
handler.accept(newSize.doubleValue());
size.removeListener(this);
}
}
};
size.addListener(listener);
}
Pour ce code, vous devez importer
import java.awt.Dimension;
import java.awt.Toolkit;
Puis
Dimension d= Toolkit.getDefaultToolkit().getScreenSize(); // get screen size
primaryStage.show(); //show stage because you wouldn't be able to get Height & width of the stage
primaryStage.setX(d.width/2-(primaryStage.getWidth()/2));
primaryStage.setY(d.height/2-(primaryStage.getHeight()/2));
Si vous voulez le faire avant que cette étape ne soit affichée, alors à l'endroit de primaryStage.getWidth () / 2 remplacez-le par la hauteur que vous allez passer dans le constructeur scenes.
primaryStage.setX(d.width/2-(300/2));
primaryStage.setY(d.height/2-(300/2));
Scene scene = new Scene(root , 300 ,300);
Je sais que ce poste a été répondu il y a environ trois ans et demi, mais il me semble que tout le monde a négligé le problème.
Vous avez juste besoin de taper le stage.centerOnScreen();
juste après le stage.show()
parce que si vous l'écrivez avant que le code ne soit exécuté une fois et ensuite il passe à son état d'origine(c'est ainsi que c'est expliqué dans ma tête).