如何让JavaFX识别当前屏幕是4K还是1080P?
嘿,这个问题我之前折腾过好一阵,咱们来理清楚到底是怎么回事~
首先,你拿到的两个DPI值都没错,只是它们代表的含义完全不同:
Screen.getPrimary().getDpi()是JavaFX提供的逻辑DPI,也就是系统的基准DPI(通常Windows默认是96,Mac是72),它不受系统缩放设置的影响,是JavaFX用来计算界面元素大小的参考值。Toolkit.getDefaultToolkit().getScreenResolution()是AWT的API,返回的是物理DPI,是根据屏幕的实际像素数和物理尺寸计算出来的(比如15寸1080P屏幕的DPI大概是141,27寸4K屏幕大概是163)。
但其实,你要检测1080P/4K来调整程序尺寸和位置,依赖DPI并不是最优方案——因为同样是1080P,不同尺寸的屏幕DPI差异很大,反过来,相同DPI的屏幕也可能是不同的分辨率等级。
更靠谱的方案:直接获取屏幕物理像素尺寸
JavaFX的Screen类提供了足够的信息,结合缩放因子就能准确拿到屏幕的物理像素:
- 先获取主屏幕的逻辑尺寸和缩放因子
- 用逻辑尺寸乘以缩放因子,得到实际的物理像素宽高
- 根据物理像素判断是1080P(1920×1080)、4K(3840×2160)还是其他等级
给你个完整的示例代码,直接就能跑:
import javafx.application.Application; import javafx.geometry.Rectangle2D; import javafx.stage.Screen; import javafx.stage.Stage; public class ScreenAdjustDemo extends Application { @Override public void start(Stage primaryStage) { Screen primaryScreen = Screen.getPrimary(); // 1. 获取逻辑屏幕尺寸(系统缩放后的,比如Windows开150%缩放,1920×1080会变成1280×720) Rectangle2D logicalBounds = primaryScreen.getBounds(); // 如果要避开任务栏等系统UI,用getVisualBounds()代替getBounds() // Rectangle2D usableBounds = primaryScreen.getVisualBounds(); // 2. 获取系统缩放因子 double scaleX = primaryScreen.getOutputScaleX(); double scaleY = primaryScreen.getOutputScaleY(); // 3. 计算物理像素尺寸 double physicalWidth = logicalBounds.getWidth() * scaleX; double physicalHeight = logicalBounds.getHeight() * scaleY; // 判断分辨率等级 String resLevel; if (physicalWidth >= 3840 && physicalHeight >= 2160) { resLevel = "4K"; } else if (physicalWidth >= 1920 && physicalHeight >= 1080) { resLevel = "1080P"; } else { resLevel = "其他分辨率"; } System.out.println("当前屏幕分辨率等级:" + resLevel); // 4. 调整程序窗口的尺寸和位置(基于逻辑尺寸,JavaFX会自动适配缩放) primaryStage.setWidth(logicalBounds.getWidth() * 0.7); // 占屏幕宽度的70% primaryStage.setHeight(logicalBounds.getHeight() * 0.7); // 占屏幕高度的70% // 窗口居中 primaryStage.setX((logicalBounds.getWidth() - primaryStage.getWidth()) / 2); primaryStage.setY((logicalBounds.getHeight() - primaryStage.getHeight()) / 2); primaryStage.setTitle("分辨率适配Demo"); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
额外注意点:
- 如果程序需要支持多屏幕,记得遍历
Screen.getScreens()来获取所有屏幕的信息,而不是只取主屏幕 - 如果要让窗口不覆盖任务栏、Dock等系统UI,用
getVisualBounds()代替getBounds()来计算可用区域
这样就能准确根据屏幕的实际分辨率等级来调整你的程序啦~
内容的提问来源于stack exchange,提问作者George Wang
相关产品推荐
相关产品推荐

