【问题标题】:JOptionPane icon gets cropped in Windows 10JOptionPane 图标在 Windows 10 中被裁剪
【发布时间】:2016-02-28 20:11:37
【问题描述】:

我正在使用以下代码在 Java Swing 中显示错误对话框:

JOptionPane.showMessageDialog(null, "Arquivo de imagem não encontrado. Por gentileza, altere o caminho do arquivo.", "Erro",  JOptionPane.ERROR_MESSAGE);

使用 Windows 10 默认外观:

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

但是图标看起来像这样被裁剪了:

关于如何解决这个问题的任何想法?

这里是 SSCCE:

import javax.swing.JOptionPane;
import javax.swing.UIManager;

public class SSCCE {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            JOptionPane.showMessageDialog(null, "Error message", "Error",  JOptionPane.ERROR_MESSAGE);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

}

【问题讨论】:

标签: java swing windows-10 look-and-feel


【解决方案1】:

mkJ720 的回答效果很好,但图标 ID 已关闭。以下是更正的:

String[][] icons = {
    {"OptionPane.warningIcon",     "65581"},
    {"OptionPane.questionIcon",    "65583"},
    {"OptionPane.errorIcon",       "65585"},
    {"OptionPane.informationIcon", "65587"}
};

【讨论】:

  • 如果有人仍在寻找解决此问题的方法,这组图标 ID 在我的机器上似乎是正确的,但对于完全相同的消息,测试人员的机器上的图标不同。我的是迷你台式机,她的是笔记本电脑,都是windows10,系统更新完全由IT部门控制。
  • 想知道你是如何得到号码的,例如每个图标的“65581”、“65583”等。又试了几台笔记本电脑;在某些笔记本电脑上,错误消息带有红色 X 图标,而确认消息带有蓝色 ?图标;在其他笔记本电脑上,错误消息为蓝色?图标,并且确认消息带有黄色 !图标。不同机器上的不同结果!
【解决方案2】:

看起来 Oracle 终于注意到了这一点和 will fix it in JDK 9,但对于那些不愿意提供自定义图标的人来说,暂时这里是一个 qiuck、hacky 和依赖于 Windows 的解决方案。

在您致电UIManager.setLookAndFeel() 后插入此代码:

try
{
    String[][] icons =
    {
        {"OptionPane.errorIcon", "65581"},
        {"OptionPane.warningIcon", "65577"},
        {"OptionPane.questionIcon", "65579"},
        {"OptionPane.informationIcon", "65583"}
    };
    //obtain a method for creating proper icons
    Method getIconBits = Class.forName("sun.awt.shell.Win32ShellFolder2").getDeclaredMethod("getIconBits", new Class[]{long.class, int.class});
    getIconBits.setAccessible(true);
    //calculate scaling factor
    double dpiScalingFactor = Toolkit.getDefaultToolkit().getScreenResolution() / 96.0;
    int icon32Size = (dpiScalingFactor == 1)?(32):((dpiScalingFactor == 1.25)?(40):((dpiScalingFactor == 1.5)?(45):((int) (32 * dpiScalingFactor))));
    Object[] arguments = {null, icon32Size};
    for (String[] s:icons)
    {
        if (UIManager.get(s[0]) instanceof ImageIcon)
        {
            arguments[0] = Long.valueOf(s[1]);
            //this method is static, so the first argument can be null
            int[] iconBits = (int[]) getIconBits.invoke(null, arguments);
            if (iconBits != null)
            {
                //create an image from the obtained array
                BufferedImage img = new BufferedImage(icon32Size, icon32Size, BufferedImage.TYPE_INT_ARGB);
                img.setRGB(0, 0, icon32Size, icon32Size, iconBits, 0, icon32Size);
                ImageIcon newIcon = new ImageIcon(img);
                //override previous icon with the new one
                UIManager.put(s[0], newIcon);
            }
        }
    }
}
catch (Exception e)
{
    e.printStackTrace();
}

为什么会这样

在 Windows 上,提供给应用程序的图标已按当前 DPI 设置进行缩放(96 = 无缩放,120 = +25%,144 = +50%)。 不幸的是,Java 总是假定图标的大小是 16x16 或 32x32,但事实并非如此。 上面的代码利用 Java 使用的本地方法 sun.awt.shell.Win32ShellFolder2.getIconBits() 来获取 OS 图标,但提供了适当的大小。 这种方法将来可能会变得不可用,因为Win32ShellFolder2 不是 API 的一部分,可能会被完全修改或删除,但到目前为止,这是唯一保留原生图标的方法。

【讨论】:

  • 我尝试了我的安装,但图标小得多且不正确。这是一个带有警告图标的 JOptionPane
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 2013-10-07
相关资源
最近更新 更多