在 JMenuBar 可见后更新 JMenu 和 JMenu 字体
Update JMenu and JMenu font after JMenuBar is visible
下面的代码创建了一个简单的 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));
}
}
}
设置字体后,需要让层级中的每个组件调用更新它UI - SwingUtilities有一个方便的方法
UIManager.put("Menu.font", menuFont);
SwingUtilities.updateComponentTreeUI( Main.this );
使用FontUIResource class 例如
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));
}
}
}
mB = new MenuBar();
setJMenuBar(new MenuBar());
您的 ActionListener 没有在您添加到框架的菜单栏上工作。
代码应该是:
mB = new MenuBar();
//setJMenuBar(new MenuBar());
setJMenuBar(mB);
getComponents() 方法不是递归的。因此,您的循环只会将 JMenu 组件添加到 JMenuBar,而不是 JMenuItems。
此外,在创建字体时,为什么不使用更大的字体大小,这样您就可以真正看到是否有变化。
另外,在您发布的代码中,在创建组件之前设置 UIManager 字体属性违背了拥有按钮的目的。您的菜单已经是所需的字体。
也许你可以试试这个:
public class MenuFontChange {
public static void changeMenuFont(JMenuBar jBar, Font font) {
Component[] components = jBar.getComponents();
for (Component component : components) {
component.setFont(font);
changeMenuItemFont((JMenu) component, font);
}
}
public static void changeMenuItemFont(JMenu jMenu, Font font) {
int n = jMenu.getItemCount();
for (int i = 0; i < n; i++) {
JMenuItem item = jMenu.getItem(i);
item.setFont(font);
}
}
下面的代码创建了一个简单的 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));
}
}
}
设置字体后,需要让层级中的每个组件调用更新它UI - SwingUtilities有一个方便的方法
UIManager.put("Menu.font", menuFont); SwingUtilities.updateComponentTreeUI( Main.this );
使用FontUIResource class 例如
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));
}
}
}
mB = new MenuBar();
setJMenuBar(new MenuBar());
您的 ActionListener 没有在您添加到框架的菜单栏上工作。
代码应该是:
mB = new MenuBar();
//setJMenuBar(new MenuBar());
setJMenuBar(mB);
getComponents() 方法不是递归的。因此,您的循环只会将 JMenu 组件添加到 JMenuBar,而不是 JMenuItems。
此外,在创建字体时,为什么不使用更大的字体大小,这样您就可以真正看到是否有变化。
另外,在您发布的代码中,在创建组件之前设置 UIManager 字体属性违背了拥有按钮的目的。您的菜单已经是所需的字体。
也许你可以试试这个:
public class MenuFontChange {
public static void changeMenuFont(JMenuBar jBar, Font font) {
Component[] components = jBar.getComponents();
for (Component component : components) {
component.setFont(font);
changeMenuItemFont((JMenu) component, font);
}
}
public static void changeMenuItemFont(JMenu jMenu, Font font) {
int n = jMenu.getItemCount();
for (int i = 0; i < n; i++) {
JMenuItem item = jMenu.getItem(i);
item.setFont(font);
}
}