java - JMenuBar 可见后更新 JMenu 和 JMenu 字体

标签 java swing fonts jmenu

下面的代码创建了一个简单的 GUI,中间有一个按钮,单击该按钮后,应更新 JMenuBar 组件的字体。为此,setMyFont 方法会在 JButton 上的 ActionListener 中触发。然而,经过几次列出的尝试后,我未能完成此任务,但我不知道为什么。 setMyFont中使用的代码如下

public void setMyFont(Font f, Font f2) {
    //Attempt 1 in the hope it would autodetect that font
    //had changed and just update
    menuFont = f;
    menuItemFont = f2;

    //Attempt 2 in the hope on the repaint it would update 
    //the font with the new UIManager properties
    UIManager.put("Menu.font", menuFont);
    UIManager.put("MenuItem.font", menuItemFont);

    //Attempt 3 in the hope that going over each component 
    //individually would update the font
    for(Component comp: getComponents()) {
        if(comp instanceof JMenu) {
            comp.setFont(menuFont);
        } else {
            comp.setFont(menuItemFont);
        }
    }

    validate();
    repaint();
}

使用当前代码的组件上的字体没有更新是否有原因?另外,即使组件已经创建,我如何更改代码以允许字体更新?

<小时/>

SSCCE 完整代码

import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.UIManager;

public class Main extends JFrame {
    private static final long serialVersionUID = 3206847208968227199L;
    JButton but;
    MenuBar mB;

    private Main() {
        setSize(600, 600);

        mB = new MenuBar();
        setJMenuBar(new MenuBar());

        but = new JButton("Change Font");
        but.addActionListener(new CustomActionListener());
        add(but);

        setVisible(true);
        setLocationRelativeTo(null);
    }

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

    private class MenuBar extends JMenuBar {
        private static final long serialVersionUID = -2055260049565317972L;
        Font menuFont = new Font("Courier", Font.ITALIC + Font.BOLD, 12);
        Font menuItemFont = new Font("sans-serif", 0, 12);
        JMenu menu, subMenu;

        MenuBar() {
            UIManager.put("Menu.font", menuFont);
            UIManager.put("MenuItem.font", menuItemFont);

            menu = new JMenu("Menu");

            subMenu = new JMenu("Sub Menu");
            subMenu.add(new JMenuItem("Sub Item"));
            subMenu.add(new JMenu("Sub Menu"));
            menu.add(subMenu);

            menu.add(new JMenuItem("Sub Item"));
            menu.add(new JMenu("Sub Menu"));

            add(menu);

            menu = new JMenu("Another Menu");
            menu.add(new JMenu("Sub Menu"));
            menu.add(new JMenuItem("Sub Item"));
            menu.add(new JMenu("Sub Menu"));
            add(menu);
        }

        public void setMyFont(Font f, Font f2) {
            //Attempt 1 in the hope it would autodetect that font
            //had changed and just update
            menuFont = f;
            menuItemFont = f2;

            //Attempt 2 in the hope on the repaint it would update 
            //the font with the new UIManager properties
            UIManager.put("Menu.font", menuFont);
            UIManager.put("MenuItem.font", menuItemFont);

            //Attempt 3 in the hope that going over each component 
            //individually would update the font
            for(Component comp: getComponents()) {
                if(comp instanceof JMenu) {
                    comp.setFont(menuFont);
                } else {
                    comp.setFont(menuItemFont);
                }
            }

            validate();
            repaint();
        }
    }

    private class CustomActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            mB.setMyFont(new Font("sans-serif", 0, 12), new Font("Courier", Font.ITALIC + Font.BOLD, 12));
        }
    }
}

最佳答案

  1. 设置字体后,您需要让层次结构中的每个组件调用更新其 UI - SwingUtilities为此有一个方便的方法

    UIManager.put("Menu.font",  menuFont);
    SwingUtilities.updateComponentTreeUI( Main.this );
    
  2. 使用FontUIResource类例如

    FontUIResource menuFont = new FontUIResource("Courier", Font.ITALIC + Font.BOLD, 12);
    

以下代码改编自已发布的 SSCCE,适用于我:

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
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.plaf.FontUIResource;

public class Main extends JFrame {
    private static final long serialVersionUID = 3206847208968227199L;
    JButton but;
    MenuBar mB;

    private Main() {
        setSize(600, 600);

        mB = new MenuBar();
        setJMenuBar(mB);

        but = new JButton("Change Font");
        but.addActionListener(new CustomActionListener());
        add(but);

        setVisible(true);
        setLocationRelativeTo(null);
    }

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

    private class MenuBar extends JMenuBar {
        private static final long serialVersionUID = -2055260049565317972L;
        Font menuFont = new FontUIResource("Courier", Font.ITALIC + Font.BOLD, 12);
        Font menuItemFont = new FontUIResource("sans-serif", 0, 12);
        JMenu menu, subMenu;

        MenuBar() {
            UIManager.put("Menu.font", menuFont);
            UIManager.put("MenuItem.font", menuItemFont);

            menu = new JMenu("Menu");

            subMenu = new JMenu("Sub Menu");
            subMenu.add(new JMenuItem("Sub Item"));
            subMenu.add(new JMenu("Sub Menu"));
            menu.add(subMenu);

            menu.add(new JMenuItem("Sub Item"));
            menu.add(new JMenu("Sub Menu"));

            add(menu);

            menu = new JMenu("Another Menu");
            menu.add(new JMenu("Sub Menu"));
            menu.add(new JMenuItem("Sub Item"));
            menu.add(new JMenu("Sub Menu"));
            add(menu);
        }

        public void setMyFont(Font f, Font f2) {

            menuFont = f;
            menuItemFont = f2;
            UIManager.put("Menu.font", menuFont);
            UIManager.put("MenuItem.font", menuItemFont);
            SwingUtilities.updateComponentTreeUI(Main.this);
        }
    }

    private class CustomActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            mB.setMyFont(new FontUIResource("sans-serif", 0, 12), new FontUIResource("Courier", Font.ITALIC + Font.BOLD, 12));
        }
    }
}

关于java - JMenuBar 可见后更新 JMenu 和 JMenu 字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38383694/

相关文章:

java - 将格式为 "dd-MM-yyyy HH:mm:ss"的日期字段索引到 ElasticSearch 2.2.1 中

java - 从 jDateChooser 获取值并保存到 MS sql DB

python - 编辑 Bokeh 段落小部件的字体大小/样式

fonts - 我如何确定正在运行的 urxvt 使用的是什么字体?

java - 在 DOM4j 文档中搜索元素名称的有效方法

java - 从 base64 编码恢复文件名和扩展名

java - Swing JTree 节点可以是哪些类型的对象?

java - Java中如何在按钮中设置单键助记符?

java - 从使用 GridLayout 设置的 JPanel 中删除最后一行

html - 占位符字体不变