JavaFX 无边框窗口可拉伸拖曳

本文介绍了一个使用JavaFX实现的窗口尺寸动态调整功能,通过监听鼠标移动和拖拽事件,能够智能地调整窗口大小,同时确保窗口尺寸不会低于设定的最小宽度和高度。该功能通过设置不同的鼠标光标来指示用户当前的调整状态,提供了更友好的用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自己改了一点,参考自:https://www.cnblogs.com/moonlightL/p/5982679.html

public class Main extends Application {

    //窗体拉伸属性
    private static boolean isRight;// 是否处于右边界调整窗口状态
    private static boolean isBottomRight;// 是否处于右下角调整窗口状态
    private static boolean isBottom;// 是否处于下边界调整窗口状态
    private final static int RESIZE_WIDTH = 5;// 判定是否为调整窗口状态的范围与边界距离
    private final static double MIN_WIDTH = 300;// 窗口最小宽度
    private final static double MIN_HEIGHT = 250;// 窗口最小高度
    private double xOffset = 0;
    private double yOffset = 0;

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 800, 450));
        primaryStage.initStyle(StageStyle.TRANSPARENT);

        root.setOnMouseMoved(event -> {
            event.consume();
            double x = event.getSceneX();
            double y = event.getSceneY();
            double width = primaryStage.getWidth();
            double height = primaryStage.getHeight();
            Cursor cursorType = Cursor.DEFAULT;// 鼠标光标初始为默认类型,若未进入调整窗口状态,保持默认类型

            // 先将所有调整窗口状态重置
            isRight = isBottomRight = isBottom = false;
            if (y >= height - RESIZE_WIDTH) {
                if (x <= RESIZE_WIDTH) {// 左下角调整窗口状态

                } else if (x >= width - RESIZE_WIDTH) {// 右下角调整窗口状态
                    isBottomRight = true;
                    cursorType = Cursor.SE_RESIZE;
                } else {// 下边界调整窗口状态
                    isBottom = true;
                    cursorType = Cursor.S_RESIZE;
                }
            } else if (x >= width - RESIZE_WIDTH) {// 右边界调整窗口状态
                isRight = true;
                cursorType = Cursor.E_RESIZE;
            }
            // 最后改变鼠标光标
            root.setCursor(cursorType);
        });

        root.setOnMouseDragged(event -> {
            double x = event.getSceneX();
            double y = event.getSceneY();
            // 保存窗口改变后的x、y坐标和宽度、高度,用于预判是否会小于最小宽度、最小高度
            double nextX = primaryStage.getX();
            double nextY = primaryStage.getY();
            double nextWidth = primaryStage.getWidth();
            double nextHeight = primaryStage.getHeight();

            if (isRight || isBottomRight) {// 所有右边调整窗口状态
                nextWidth = x;
            }
            if (isBottomRight || isBottom) {// 所有下边调整窗口状态
                nextHeight = y;
            }
            if (nextWidth <= MIN_WIDTH) {// 如果窗口改变后的宽度小于最小宽度,则宽度调整到最小宽度
                nextWidth = MIN_WIDTH;
            }
            if (nextHeight <= MIN_HEIGHT) {// 如果窗口改变后的高度小于最小高度,则高度调整到最小高度
                nextHeight = MIN_HEIGHT;
            }
            // 最后统一改变窗口的x、y坐标和宽度、高度,可以防止刷新频繁出现的屏闪情况
            primaryStage.setX(nextX);
            primaryStage.setY(nextY);
            primaryStage.setWidth(nextWidth);
            primaryStage.setHeight(nextHeight);
            if(!isBottom && !isBottomRight && !isRight)
            {
                primaryStage.setX(event.getScreenX() - xOffset);
                primaryStage.setY(event.getScreenY() - yOffset);
            }
        });

        root.setOnMousePressed(event -> {
            xOffset = event.getSceneX();
            yOffset = event.getSceneY();
        });



        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

 

<think>嗯,用户想在JavaFX中去掉Stage的边框,并且自定义最小化和关闭按钮。首先,我需要回忆一下JavaFX中Stage的相关设置。Stage的样式可以通过initStyle方法来设置,可能使用的样式包括UNDECORATED、TRANSPARENT等。去掉边框的话,应该使用StageStyle.UNDECORATED,这样标题栏和边框都会消失。 不过,这样的话默认的窗口控制按钮(最小化、最大化、关闭)也会被移除,用户需要自己添加这些功能。所以接下来要考虑如何创建自定义的按钮,并为这些按钮添加事件处理。比如,关闭按钮可以调用stage.close(),最小化按钮则调用stage.setIconified(true)。 另外,用户可能还希望窗口可以拖动,因为去除了标题栏后,通常拖动功能会失效。这时候需要在某个布局面板上添加鼠标事件监听器,记录拖拽的起始坐标,然后调整窗口的位置。 代码结构方面,首先需要设置Stage的样式为UNDECORATED,然后创建HBox或者其他的布局容器来放置自定义的按钮。按钮的样式可以通过CSS来设置,比如背景颜色、悬停效果等,以符合应用的整体设计。 同时,需要注意,使用UNDECORATED样式后,窗口可能无法通过操作系统默认的方式移动,所以必须自己实现拖动功能。这通常通过监听鼠标的按下、拖拽事件,计算偏移量,然后更新窗口的位置来实现。 最后,测试一下代码,确保按钮功能正常,窗口可以拖动,并且没有边框。如果有问题,可能需要检查CSS是否正确应用,或者事件处理是否正确绑定。 用户提供的参考引用中提到了一些关于JAR运行和查看源码的内容,虽然可能与当前问题无直接关联,但需要注意环境兼容性,比如Java版本是否支持使用的JavaFX特性。例如,某些StageStyle可能在旧版本中不可用,需要确认用户的环境是否符合要求。 总结步骤:设置Stage样式→创建自定义按钮→实现按钮功能→添加窗口拖动支持→应用CSS样式美化。这样应该能满足用户的需求。</think>在JavaFX中去除Stage边框并自定义控制按钮,可通过以下步骤实现: ### 1. 去除默认边框 使用`StageStyle.UNDECORATED`样式初始化窗口: ```java Stage stage = new Stage(); stage.initStyle(StageStyle.UNDECORATED); ``` ### 2. 创建自定义按钮布局 ```java HBox controlBox = new HBox(10); Button closeButton = new Button("✕"); Button minimizeButton = new Button("-"); // 添加CSS样式 controlBox.setStyle("-fx-background-color: #f0f0f0; -fx-padding: 5;"); closeButton.setStyle("-fx-background-radius: 15; -fx-min-width: 30; -fx-text-fill: #ff4444;"); closeButton.setOnMouseEntered(e -> closeButton.setStyle("-fx-background-color: #ffcccc;")); closeButton.setOnMouseExited(e -> closeButton.setStyle("")); ``` ### 3. 实现按钮功能 ```java // 关闭按钮事件 closeButton.setOnAction(e -> stage.close()); // 最小化按钮事件 minimizeButton.setOnAction(e -> stage.setIconified(true)); // 窗口拖动实现 final Delta dragDelta = new Delta(); scene.setOnMousePressed(mouseEvent -> { dragDelta.x = stage.getX() - mouseEvent.getScreenX(); dragDelta.y = stage.getY() - mouseEvent.getScreenY(); }); scene.setOnMouseDragged(mouseEvent -> { stage.setX(mouseEvent.getScreenX() + dragDelta.x); stage.setY(mouseEvent.getScreenY() + dragDelta.y); }); class Delta { double x, y; } ``` ### 4. 完整示例结构 ```java public class CustomStage extends Application { @Override public void start(Stage primaryStage) { VBox root = new VBox(); Scene scene = new Scene(root, 400, 300); // 添加控制按钮和内容 root.getChildren().addAll(createControlBar(primaryStage), createContent()); primaryStage.initStyle(StageStyle.UNDECORATED); primaryStage.setScene(scene); primaryStage.show(); } private HBox createControlBar(Stage stage) { // 返回包含自定义按钮的布局 } } ``` ### 注意事项 - 窗口样式需在`show()`方法调用前设置 - 建议使用CSS伪类实现按钮悬停动画效果 - 可通过`-fx-shape`属性自定义按钮形状[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾无法无天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值