一、問題場景
同樣的,隱藏掉窗體的默認標題欄也會導致窗體大小自由拉伸功能的失效。
二、解決思路
判斷鼠標在窗體的位置,改變鼠標樣式,給窗體組件添加拖拽事件監聽器,根據鼠標移動位置改變窗體大小。
三、代碼實現
/** * 程序入口 * @author Light */ public class JavaFXTest extends Application { @Override public void start(Stage stage) { stage.initStyle(StageStyle.TRANSPARENT); VBox root = new VBox(); root.setId("root"); // 引入樣式 root.getStylesheets().add(JavaFXTest.class.getResource("/resources/style.css").toString()); //頂部 VBox top = new VBox(); top.setId("top"); top.setPrefSize(300,26); // 標題欄 AnchorPane title = new AnchorPane(); Label close = new Label(); close.setPrefWidth(33); close.setPrefHeight(26); close.setId("winClose");//winClose css樣式Id title.getChildren().add(close); AnchorPane.setRightAnchor(close, 0.0); AnchorPane.setTopAnchor(close, 5.0); top.getChildren().add(title); // 內容 VBox content = new VBox(); content.setPrefWidth(300); content.setMinHeight(200); // 組裝 root.getChildren().addAll(top, content); Scene scene = new Scene(root); stage.setScene(scene); // 拖動監聽器 DragUtil.addDragListener(stage, top); // 添加窗體拉伸效果 DrawUtil.addDrawFunc(stage, root); // 顯示 stage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } }
/** * 拉伸工具類 * @author Light */ public class DrawUtil { //窗體拉伸屬性 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;// 窗口最小高度 public static void addDrawFunc(Stage stage,VBox root) {
root.setOnMouseMoved((MouseEvent event) -> { event.consume(); double x = event.getSceneX(); double y = event.getSceneY(); double width = stage.getWidth(); double height = stage.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((MouseEvent event) -> { double x = event.getSceneX(); double y = event.getSceneY(); // 保存窗口改變后的x、y坐標和寬度、高度,用於預判是否會小於最小寬度、最小高度 double nextX = stage.getX(); double nextY = stage.getY(); double nextWidth = stage.getWidth(); double nextHeight = stage.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坐標和寬度、高度,可以防止刷新頻繁出現的屏閃情況 stage.setX(nextX); stage.setY(nextY); stage.setWidth(nextWidth); stage.setHeight(nextHeight); }); } }
效果演示圖: