JavaFX 制作无装饰可移动的窗口并使窗口位于屏幕中央
- 去掉窗口修饰,有两种方式
primaryStage.initStyle(StageStyle.TRANSPARENT);//去掉窗口修饰同时让弹出窗口透明
primaryStage.initStyle(StageStyle.UNDECORATED);
- 窗口移动处理主要是注意偏移量就可以了
root.setOnMousePressed(new EventHandler<MouseEvent>() {
/*
* 鼠标按下时,记下相对于 root左上角(0,0) 的 x, y坐标, 也就是x偏移量 = x - 0, y偏移量 = y - 0
*/
@Override
public void handle(MouseEvent event) {
xOffset = event.getSceneX();
yOffset = event.getSceneY();
}
});
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
/*
* 根据偏移量设置primaryStage新的位置
*/
@Override
public void handle(MouseEvent event) {
primaryStage.setX(event.getScreenX() - xOffset);
primaryStage.setY(event.getScreenY() - yOffset);
}
});
- 窗口居中,本来Stage也有一个centerOnScreen()来使居中窗口,但实际它的效果是居中偏上的,可以看下这个方法的相关源码(在javafx.stage.Window里面),找到原因
private static final float CENTER_ON_SCREEN_X_FRACTION = 1.0f / 2;
private static final float CENTER_ON_SCREEN_Y_FRACTION = 1.0f / 3;//注意这里,它并不是除以2
public void centerOnScreen() {
xExplicit = false;
yExplicit = false;
if (impl_peer != null) {
Rectangle2D bounds = getWindowScreen().getVisualBounds();
double centerX = bounds.getMinX() + (bounds.getWidth() - getWidth()) * CENTER_ON_SCREEN_X_FRACTION;
double centerY = bounds.getMinY() + (bounds.getHeight() - getHeight()) * CENTER_ON_SCREEN_Y_FRACTION;
x.set(centerX);
y.set(centerY);
peerBoundsConfigurator.setLocation(centerX, centerY, CENTER_ON_SCREEN_X_FRACTION,
CENTER_ON_SCREEN_Y_FRACTION);
applyBounds();
}
}
- 所以还是要手动设置Stage的位置,注意在show()方法后面。
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
primaryStage.setX((screenBounds.getWidth() - width) / 2);
primaryStage.setY((screenBounds.getHeight() - height) / 2);
- 完整代码
Demo.java
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Demo extends Application {
// 定义偏移量,用于处理窗口移动
private double xOffset = 0;
private double yOffset = 0;
@Override
public void start(Stage primaryStage) {
try {
// 去掉窗口修饰,有两种方式
// primaryStage.initStyle(StageStyle.TRANSPARENT);//同时让弹出窗口透明
primaryStage.initStyle(StageStyle.UNDECORATED);
BorderPane root = new BorderPane();
root.setOnMousePressed(new EventHandler<MouseEvent>() {
/*
* 鼠标按下时,记下相对于 root左上角(0,0) 的 x, y坐标, 也就是x偏移量 = x - 0, y偏移量 = y - 0
*/
@Override
public void handle(MouseEvent event) {
xOffset = event.getSceneX();
yOffset = event.getSceneY();
}
});
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
/*
* 根据偏移量设置primaryStage新的位置
*/
@Override
public void handle(MouseEvent event) {
primaryStage.setX(event.getScreenX() - xOffset);
primaryStage.setY(event.getScreenY() - yOffset);
}
});
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("demo.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
primaryStage.setX((screenBounds.getWidth() - 400) / 2);
primaryStage.setY((screenBounds.getHeight() - 400) / 2);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
demo.css
这个文件里面没内容。