动态更改字体会导致某些组件出现问题



首先,我知道如何更新整个UI的字体。我使用以下代码:

private static void setUIFont(final FontUIResource f) {
    for (Map.Entry<Object, Object> entry : UIManager.getLookAndFeelDefaults().entrySet()) {
        Object key = entry.getKey();
        Object value = UIManager.getLookAndFeelDefaults().get(key);
        if (value != null && value instanceof FontUIResource) {
            UIManager.getLookAndFeelDefaults().put(key, f);
        }
    }
    dynamicallyUpdateRootPane(f);
}

private static void dynamicallyUpdateRootPane(FontUIResource f) {
        updateComponent(rootPanel, f);
}

private static void updateComponent(Component c, FontUIResource resource) {
    if (c == null) {
        return;
    }
    if (c instanceof JComponent) {
        JComponent jc = (JComponent) c;
        jc.updateUI();
        JPopupMenu jpm = jc.getComponentPopupMenu();
        if (jpm != null) {
            updateComponent(jpm, resource);
        }
    }
    Component[] children = null;
    if (c instanceof JMenu) {
        children = ((JMenu) c).getMenuComponents();
    }
    else if (c instanceof Container) {
        children = ((Container) c).getComponents();
    }
    if (children != null) {
        for (Component child : children) {
            if (child instanceof Component) {
                updateComponent(child, resource);
            }
        }
    }
    int style = Font.PLAIN;
    Font f = c.getFont();
    if (f == null) {
        f = getFontUIResource(16); // default
    }
    if (f.isBold()) {
        style = Font.BOLD;
    }
    else if (f.isItalic()) {
        style = Font.ITALIC;
    }
    if (c instanceof JEditorPane) {
        ((JEditorPane) c).putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
    }
    c.setFont(resource.deriveFont(style));
}

设置键后,我需要递归地更新根面板,因为不是所有组件都更改其外观。这个代码几乎可以运行95%。我有一些问题与JButton的和JMenuItem的。

假设我用大字体启动程序,并动态地将其更改为小字体。我的按钮的字体变化(这很好…),但当我悬停他们的字体从小变大。当我把鼠标拿开时,它又从大变小了,我不知道为什么或如何处理它,测试了很多,但似乎没有任何工作。当我将元素悬停时,它会使用不同的字体。

另一个奇怪的事情是我的菜单项。菜单栏会更改其字体(菜单),但菜单项不会更改。我试图手动更新它们,例如手动设置字体,但它根本不起作用。

希望你们能帮助我,因为我花了太多的时间(甚至几天)在这上面。顺便说一句。我正在使用光轮。

问好

** UPDATE **

修复了我的代码和工作示例。现在,在我动态更改字体大小后,GUI上的所有组件都将正确显示。有自动取款机。没有时间清理我的代码,但是对于那些对解决方案感兴趣的人来说,代码应该是清晰的。

    import java.awt.Component;
    import java.awt.Container;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Map;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.UIManager.LookAndFeelInfo;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.plaf.FontUIResource;

    public class Test extends JFrame {
        /**
         * 
         */
        private static final long serialVersionUID = 1865556053669711743L;

        public static void main(String[] args) {
            new Test();
        }

        public Test() {
            setLaf();
            prepareFrame();
            setJMenuBar(new MyMenuBar());
            pack();
            setVisible(true);
        }

        private void prepareFrame() {
            setLayout(new FlowLayout(FlowLayout.RIGHT));
            final JComboBox<String> combo = new JComboBox<>(new String[] {
                            "Small", "Large", "Larger"
            });
            JButton button = new JButton("Change");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int index = combo.getSelectedIndex();
                    switch (index) {
                        case 0:
                            setUIFont(getFontUIResource(14));
                            break;
                        case 1:
                            setUIFont(getFontUIResource(16));
                            break;
                        case 2:
                            setUIFont(getFontUIResource(17));
                            break;
                    }
                    pack();
                    //SwingUtilities.updateComponentTreeUI(Test.this);
                }
            });
            getContentPane().add(combo);
            getContentPane().add(button);
        }

        private void setLaf() {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    try {
                        UIManager.setLookAndFeel(info.getClassName());
                    }
                    catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                                    | UnsupportedLookAndFeelException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        private class MyMenuBar extends JMenuBar {
            /**
             * 
             */
            private static final long serialVersionUID = 1434003372646915700L;

            public MyMenuBar() {
                JMenu menu1 = new JMenu("File");
                JMenu menu2 = new JMenu("Help");
                menu1.add(new JMenuItem("This is a test"));
                menu1.add(new JMenuItem("This is a test"));
                menu1.add(new JMenuItem("This is a test"));
                menu1.add(new JMenuItem("This is a test"));
                menu2.add(new JMenuItem("This is a test"));
                menu2.add(new JMenuItem("This is a test"));
                add(menu1);
                add(menu2);
            }
        }

        private FontUIResource getFontUIResource(int size) {
            return new FontUIResource(new Font("Arial", Font.PLAIN, size));
        }

        private void setUIFont(final FontUIResource f) {
            for (Map.Entry<Object, Object> entry : UIManager.getLookAndFeelDefaults().entrySet()) {
                Object key = entry.getKey();
                Object value = UIManager.getLookAndFeelDefaults().get(key);
                if (value != null && value instanceof FontUIResource) {
                    UIManager.getLookAndFeelDefaults().put(key, f);
                }
            }
            dynamicallyUpdateRootPane(f);
        }

        private void dynamicallyUpdateRootPane(FontUIResource f) {
            updateComponent(this, f);
        }

private void updateComponent(Component c, FontUIResource resource) {
    if (c == null) {
        return;
    }
    if (c instanceof JComponent) {
        JComponent jc = (JComponent) c;
        jc.updateUI();
        JPopupMenu jpm = jc.getComponentPopupMenu();
        if (jpm != null) {
            updateComponent(jpm, resource);
        }
    }
    Component[] children = null;
    if (c instanceof JMenu) {
        children = ((JMenu) c).getMenuComponents();
    }
    else if (c instanceof Container) {
        children = ((Container) c).getComponents();
    }
    if (children != null) {
        for (Component child : children) {
            if (child instanceof Component) {
                updateComponent(child, resource);
            }
        }
    }
    int style = Font.PLAIN;
    Font f = c.getFont();
    if (f == null) {
        f = getFontUIResource(16); // default
    }
    if (f.isBold()) {
        style = Font.BOLD;
    }
    else if (f.isItalic()) {
        style = Font.ITALIC;
    }
    if (c instanceof JEditorPane) {
        ((JEditorPane) c).putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
    }
    c.setFont(resource.deriveFont(style));
    }

与其编写自己的递归代码,不如将其视为LAF更改,只需调用:

SwingUtilities.updateComponentTreeUI(frame);

请参阅Swing教程中关于更改LAF的部分。

同样,也不需要在代码中调用revalidate()和repaint()。setFont(…)方法将自动调用这些方法。

我终于解决了我的问题。@camickr给了我一个很好的提示。必须修改API代码以防止一些npe。我没有时间让我的代码"更干净",但对于那些感兴趣的人,我将分享我的代码:

private void updateComponent(Component c, FontUIResource resource) {
    if (c == null) {
        return;
    }
    if (c instanceof JComponent) {
        JComponent jc = (JComponent) c;
        jc.updateUI();
        JPopupMenu jpm = jc.getComponentPopupMenu();
        if (jpm != null) {
            updateComponent(jpm, resource);
        }
    }
    Component[] children = null;
    if (c instanceof JMenu) {
        children = ((JMenu) c).getMenuComponents();
    }
    else if (c instanceof Container) {
        children = ((Container) c).getComponents();
    }
    if (children != null) {
        for (Component child : children) {
            if (child instanceof Component) {
                updateComponent(child, resource);
            }
        }
    }
    int style = Font.PLAIN;
    Font f = c.getFont();
    if (f == null) {
        f = getFontUIResource(16); // default
    }
    if (f.isBold()) {
        style = Font.BOLD;
    }
    else if (f.isItalic()) {
        style = Font.ITALIC;
    }
    if (c instanceof JEditorPane) {
        ((JEditorPane) c).putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
    }
    c.setFont(resource.deriveFont(style));
}

编辑**新增对JEditorPanes的支持

相关内容

  • 没有找到相关文章

最新更新