【问题标题】:Java loses UI settings after changing system font anti-aliasing更改系统字体抗锯齿后 Java 丢失 UI 设置
【发布时间】:2022-01-04 19:02:36
【问题描述】:

当在简单的应用程序下运行并更改字体抗锯齿(WIN+R "sysdm.cpl" -> 系统属性 -> 高级 -> 性能设置 -> 屏幕字体的平滑边缘)时,可以看到 JTextArea 获得错误的字体(如果再次切换抗锯齿,也会保留它):

import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class Main
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        JPanel mainPanel = new JPanel();
        JLabel label = new JLabel("labelMessage:");
        mainPanel.add(label);

        final JTextArea textArea = new JTextArea("textAreaMessage")
        {
//            @Override
//            public void setFont(Font f)
//            {
//                super.setFont(label.getFont());
//            }
        };
        textArea.setEditable(false);
        textArea.setOpaque(false);
        textArea.setFont(label.getFont());
        mainPanel.add(textArea);

        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setVisible(true);
    }
}

仅当取消注释 setFont 的覆盖时,它会像预期的那样工作。 当在那里设置断点时,可以看到当字体抗锯齿发生变化时,会触发一个 AATextListener:

在某些时候安装默认值: editor.setFont(UIManager.getFont(prefix /*TextArea*/ + ".font"));

所以很清楚为什么会发生,但我不知道如何以一种好的方式解决它。

可能的解决方案:

  1. 在代码中重写如上所示的方法

  2. 使用例如-Dswing.useSystemFontSettings=false(或-Dswing.aatext=trueawt.useSystemAAFontSettings)但是字体看起来很难看,所以如果没有进一步的增强是不可接受的

  3. 通过 UIManager 设置默认值

  4. 删除/禁用监听器?似乎是硬编码,不容易做到?

  5. 或 3. 可能是一个解决方案,但需要在大型遗留应用程序中进行大量工作。

注意:这只是一个简单的例子。在我们的应用程序中,问题要大得多,因为不仅丢失了设置的字体,而且几乎所有东西都丢失了,比如按钮的边框、自定义的 ComponentUI 等。所描述的如何重现它只是为了让它易于重现,这意味着我们遇到了这个例如,也自发地发出问题该应用程序运行了几个小时。然后我们看到一些 Windows 事件正在触发侦听器并破坏了我们应用程序的外观和感觉(当这种情况突然发生时,通常几乎一个小时都没有使用 PC)。

也许我也会在接下来的几天里询问 OpenJDK 社区。如果是这样,我将在此处链接票证 ID。

Windows 版本:Windows Enterprise 10 版本 20H2(内部版本 19042.1348) Java版本:zulu11.50.19-ca-jdk11.0.12-win_x64

【问题讨论】:

  • 您可以通过adding a listener 监听"awt.font.desktophints" 属性的更改,该属性的值为RenderingHints Map。见docs.oracle.com/en/java/javase/17/docs/api/java.desktop/java/…
  • 谢谢,看来问题解决了!我用代码示例更新了问题。
  • @ConstantinButzke 您可以保留原始问题,而不是用答案编辑问题,您可以简单地回答自己的问题。这在堆栈溢出中是允许的。如果你愿意,你仍然可以这样做。我建议你这样做。
  • 我不确定删除所有现有的桌面提示侦听器是一个好方法。它可能会在其他平台上引起问题,并且在其他版本的 Java 中可能根本无法工作。它当然既没有记录也没有保证。我在想你可以添加自己的监听器,这样你就可以监控变化并相应地调整自己的组件。

标签: java swing fonts antialiasing


【解决方案1】:

监听 @VGR 提议的变化的演示。当字体抗锯齿改变时,UI 将被重新渲染。

import java.awt.Toolkit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class Main
{
    public static void main(String[] args)
    {
     
        SwingUtilities.invokeLater(() -> {
            
            final JFrame frame = new JFrame();
            final JPanel mainPanel = new JPanel();
            
            Toolkit tk = Toolkit.getDefaultToolkit();
            tk.addPropertyChangeListener("awt.font.desktophints"/*SunToolkit.DESKTOPFONTHINTS*/, new PropertyChangeListener()
            {
                @Override
                public void propertyChange(PropertyChangeEvent evt)
                {
                    SwingUtilities.invokeLater(() -> render(mainPanel));
                }
            });

            render(mainPanel);
            
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setVisible(true);
        });
    }

    private static void render(JPanel parent)
    {
        parent.removeAll();
        final JPanel panel = new JPanel();
        final JLabel label = new JLabel("labelMessage:");
        panel.add(label);
        
        final JTextArea textArea = new JTextArea("textAreaMessage");
        textArea.setEditable(false);
        textArea.setOpaque(false);
        textArea.setFont(label.getFont());
        panel.add(textArea);
        parent.add(panel);
        
        parent.revalidate();
        parent.repaint();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2023-04-07
    • 2011-01-26
    • 2015-07-31
    • 2014-02-18
    • 2011-02-11
    • 1970-01-01
    相关资源
    最近更新 更多