2016-07-14 5 views
2

以下のコードは、ボタンをクリックすると、JMenuBarコンポーネントのフォントを更新するボタンを中央に持つ簡単なGUIを作成します。これを行うにはJButtonActionListenersetMyFontメソッドが起動します。しかし、いくつかのリストされた試みの後、私はこれを達成することができませんでしたが、私はなぜそれに気づいていません。 setMyFontで使用されるコードはJMenuBarが表示された後にJMenuとJMenuフォントを更新する

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)); 
     } 
    } 
} 

答えて

4
  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)); 
     } 
    } 
} 
+1

(1+)updateComponentTree(...)メニューバーに追加されたすべてのコンポーネントを取得するために、独自の再帰的なメソッドを記述するよりも簡単ですを使用しました。ただし、フレームではなく、メニューバーでメソッドを呼び出すだけで済みます。 – camickr

+0

@camickr REは[docs](https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html#programmatic)に従ってメニューバー上で起動し、 'SwingUtilities updateComponentTreeUIメソッドを一度呼び出す'[最上位のコンテナ](https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html) – copeg

+0

@copeg答えをありがとう。残念ながら、私はおそらく間違っている、 'SwingUtilities.updateComponentTreeUI(Main.this);を呼び出す'フォントを設定した後に何もしない。私は 'setMyFont'関数の外に置くべきか、それとも動作するはずです。*私も 'FontUIResource'を実装しました。違いはありませんでした。* – Dan

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

あなたのActionListenerは、あなたがフレームに追加し、メニューバー上で作業されていません。

コードがなければならない:

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

のgetComponents()メソッドは再帰的ではありません。したがって、ループは、JMenuItemsではなく、JMenuBarに追加されたJMenuコンポーネントのみを取得します。

また、フォントを作成するときに、より大きなフォントサイズを使用しないと、実際に何か変更があるかどうかを確認できます。

また、投稿されたコードでは、コンポーネントを作成する前にUIManagerのフォントプロパティを設定すると、ボタンを持つ目的が無効になります。メニューは既に目的のフォントになります。

1

たぶん、あなたはこれを試すことができます。

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); 
     } 
    } 
関連する問題