- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我希望为某些 Swing 应用程序添加 Hi-DPI 支持,但我未能找到足以满足我需求的解决方案。我需要支持多种外观和感觉,因此情况似乎比我发现的其他帖子更复杂(这些帖子倾向于建议“调整您的 UI 大小以匹配您的字体大小”)。
一些实验发现 UIManager
包含许多可以调整的指标,让您在使应用程序 Hi-DPI 友好方面有一个良好的开端。 (UIManager-Defaults 实用程序对于探索这些非常有用!)但我发现 L&F 似乎完全彼此不同地工作:
Windows L&F 为您提供了一个不错的(不完美的)默认字体大小,并且内置图标(如复选框和窗口图标)的大小适当 - 但许多其他指标仍然不正常。
在 Metal 中,您可以单独更新 UIManager
中的字体。通过一些工作,您可以缩放内置的 IconUIResource
以匹配。
在 Nimbus 中,你可以只更新一个默认字体,其他字体就位了......但是我不知道如何缩放内置图标并使用组合框、单选按钮(等等)。 ) 渲染成功!
我从玩弄中得到的感觉是,应该可以为每个 L&F 独立创建一个特定调整的列表。这可能包括调整 Font
、Icon
、Integer
和 Dimension
的默认值。
有没有人想出好的解决办法?
谁能分享一份明确的列表,其中列出了哪些 UIDefaults
需要针对标准 L&F 进行调整?
我会很高兴有一个始终支持 Metal 和 Windows 的解决方案。
我想这样的解决方案应该是完全可重用的,并且可以为一系列 Swing 应用程序解决同样的问题。我很惊讶似乎还没有这样的实用程序。这种方法当然不会解决所有问题(例如,您仍然需要手动缩放对 setPreferredSize
等的任何调用。然后,已经支持多个 L&F 的应用程序应该尽量避免调用它。)不过,我认为它可以让许多应用程序有一个良好的开端。
我知道 JDK-9 promise 满Hi-DPI support ,但我不能等那么久 - 即使在 2017 年发布之后,我也可能有一段时间无法切换。
更新:是的 JDK-9 以后启用 HiDPI 支持,但是内置非整数缩放级别的 L&F 并没有很好地接受它并且看起来很均匀比“用 Java 8 自己破解它”更糟糕。这个问题可以在 L&F 级别得到更好的解决,但是,一些优秀的第 3 方 L&F's like FlatLaF和 Radiance做得很漂亮。强烈推荐。
最佳答案
这是基于我最初的原型(prototype)设计的解决方案。
我对某些部分不满意,例如修改“整数”和“字体”的规则非常“神奇”。这是我希望从其他人那里听到更多 Swing/L&F 经验的地方。
我已将其设为社区 Wiki,这样如果人们更愿意对此进行迭代并增加他们的知识,而不是发布他们自己的解决方案,那么请随意。
我从一个可以修改某些 ui-defaults 的界面开始:
public interface Tweaker {
void initialTweaks();
Font modifyFont(Object key, Font original);
Icon modifyIcon(Object key, Icon original);
Integer modifyInteger(Object key, Integer original);
}
可以这样调用:
public void scaleUiDefaults() {
float dpiScale = Toolkit.getDefaultToolkit().getScreenResolution() / 96f;
Tweaker delegate = createTweakerForCurrentLook(dpiScale);
tweakUiDefaults(delegate, dpiScale);
}
private Tweaker createTweakerForCurrentLook(float dpiScaling) {
String testString = UIManager.getLookAndFeel().getName().toLowerCase();
if (testString.contains("windows")) return new WindowsTweaker(dpiScaling);
if (testString.contains("nimbus")) return new NimbusTweaker(dpiScaling);
return new BasicTweaker(dpiScaling);
}
private void tweakUiDefaults(Tweaker delegate, float multiplier) {
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
delegate.initialTweaks();
for (Object key: Collections.list(defaults.keys())) {
Object original = defaults.get(key);
Object newValue = getUpdatedValue(delegate, key, original);
if (newValue != null && newValue != original) {
defaults.put(key, newValue);
}
}
}
private Object getUpdatedValue(Tweaker delegate, Object key, Object original) {
if (original instanceof Font) return delegate.modifyFont(key, (Font) original);
if (original instanceof Icon) return delegate.modifyIcon(key, (Icon) original);
if (original instanceof Integer) return delegate.modifyInteger(key, (Integer) original);
return null;
}
我将看起来被大多数 L&F 使用的功能放在基类中。这似乎无需进一步改进即可处理 Metal:
public class BasicTweaker {
protected final float scaleFactor;
protected final UIDefaults uiDefaults = UIManager.getLookAndFeelDefaults();
public BasicTweaker(float scaleFactor) {
this.scaleFactor = scaleFactor;
}
public void initialTweaks() {}
public Font modifyFont(Object key, Font original) {
// Ignores title & accelerator fonts (for example)
if (original instanceof FontUIResource && key.toString().endsWith(".font")) {
return newScaledFontUIResource(original, scaleFactor);
}
return original;
}
protected static FontUIResource newScaledFontUIResource(Font original, float scale) {
int newSize = Math.round(original.getSize() * scale);
return new FontUIResource(original.getName(), original.getStyle(), newSize);
}
public Icon modifyIcon(Object key, Icon original) {
return new IconUIResource(new ScaledIcon(original, scaleFactor));
}
public Integer modifyInteger(Object key, Integer original) {
if (!endsWithOneOf(lower(key), LOWER_SUFFIXES_FOR_SCALED_INTEGERS)) {
return original;
}
return (int) (original * scaleFactor);
}
private boolean endsWithOneOf(String text, String[] suffixes) {
return Arrays.stream(suffixes).anyMatch(suffix -> text.endsWith(suffix));
}
private String lower(Object key) {
return (key instanceof String) ? ((String) key).toLowerCase() : "";
}
private static final String[] LOWER_SUFFIXES_FOR_SCALED_INTEGERS =
new String[] { "width", "height", "indent", "size", "gap" };
}
上面使用的
class ScaledIcon
可能超出范围 - 但它本质上只是调用 ImageIcon(image).paintIcon
并修改了宽度和高度。
然后为其他 L&F 覆盖 BasicTweaker
...
window :
public class WindowsTweaker extends BasicTweaker {
public WindowsTweaker(float scaleFactor) {
// Windows already scales fonts, scrollbar sizes (etc) according to the system DPI settings.
// This lets us adjust to the REQUESTED scale factor, relative to the CURRENT scale factor
super(scaleFactor / getCurrentScaling());
}
private static float getCurrentScaling() {
int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
return dpi / 96f;
}
public Font modifyFont(Object key, Font original) {
return super.modifyFont(key, original);
}
public Icon modifyIcon(Object key, Icon original) {
return original;
}
}
雨云:
public class NimbusTweaker extends BasicTweaker {
public NimbusTweaker(float scaleFactor) {
super(scaleFactor);
}
public void initialTweaks() {
Font font = uiDefaults.getFont("defaultFont");
if (font != null) {
uiDefaults.put("defaultFont", new FontUIResource(
font.getName(), font.getStyle(), Math.round(font.getSize() * scaleFactor)));
}
}
// Setting "defaultFont" above is sufficient as this will be inherited by all others
public Font modifyFont(Object key, Font original) {
return original;
}
// Scaling Radio or CheckBox button icons leads to really weird artifacts in Nimbus? Disable
public Icon modifyIcon(Object key, Icon original) {
return original;
}
}
关于java - Java Swing 中的 HiDPI 支持提供多种外观和感觉,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38169983/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!