You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX棋盘游戏屏幕分辨率适配缩放问题求助

解决JavaFX高DPI缩放导致游戏元素超屏问题

问题出在系统开启高DPI缩放(比如125%)时,JavaFX会默认应用系统缩放比例,但你的游戏界面元素是基于1920x1080固定尺寸设计的,缩放后元素实际显示尺寸超过屏幕边界,导致异常。下面是具体解决方案:

核心思路

  1. 获取系统的实际缩放因子,对整个界面进行反向缩放,抵消系统的高DPI缩放影响
  2. 调整FXML布局,让根容器能够自适应屏幕尺寸,避免固定尺寸限制

修改后的代码实现

Main.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javax.swing.*;
import java.io.IOException;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws IOException {
        // 获取系统高DPI缩放因子
        double scaleX = Screen.getPrimary().getOutputScaleX();
        double scaleY = Screen.getPrimary().getOutputScaleY();

        Parent board = FXMLLoader.load(getClass().getResource("/board.fxml"));

        Pane innerBoard = ((Pane) board.getChildrenUnmodifiable().get(0));
        // 替换自定义断言为常规判断,避免依赖自定义类
        if (!"BOARD".equals(innerBoard.getId())) {
            throw new RuntimeException("找不到ID为BOARD的容器");
        }

        // 对根容器进行反向缩放,抵消系统缩放
        board.setScaleX(1 / scaleX);
        board.setScaleY(1 / scaleY);

        // 获取缩放后的屏幕可用尺寸
        double screenWidth = Screen.getPrimary().getVisualBounds().getWidth();
        double screenHeight = Screen.getPrimary().getVisualBounds().getHeight();

        Scene scene = new Scene(board, screenWidth, screenHeight);
        scene.getStylesheets().add(getClass().getResource("/style.css").toExternalForm());

        primaryStage.setScene(scene);
        primaryStage.setFullScreen(true);
        primaryStage.setResizable(true);
        innerBoard.setVisible(false);
        
        primaryStage.setFullScreenExitHint("");
        primaryStage.show();

        innerBoard.setVisible(true);
    }
}

修改后的FXML文件

<?xml version="1.0" encoding="UTF-8"?>
<Pane maxHeight="USE_COMPUTED_SIZE" maxWidth="USE_COMPUTED_SIZE" 
      minHeight="USE_COMPUTED_SIZE" minWidth="USE_COMPUTED_SIZE" 
      prefHeight="1080.0" prefWidth="1920.0" 
      xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Pane id="BOARD" fx:id="innerBoard" style="-fx-background-color: #cfffd1;">
         <children>
            <!-- 保留你的子元素 -->
         </children>
      </Pane>
   </children>
</Pane>

额外说明

  • 如果你使用的是JavaFX 8版本,Screen.getOutputScaleX()可能不支持,这时可以用以下方式计算缩放因子:
    // JavaFX 8兼容的缩放因子计算
    double defaultDpi = 96.0;
    double currentDpi = Toolkit.getDefaultToolkit().getScreenResolution();
    double scale = currentDpi / defaultDpi;
    
  • 移除了FXML中innerBoard的固定layoutX和layoutY,避免布局偏移,建议后续使用AnchorPane或BorderPane等布局容器管理元素位置,而非固定坐标。

内容的提问来源于stack exchange,提问作者user8322140

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:05:09