2016-07-14 12 views
2

Der folgende Code erstellt eine einfache GUI mit einer Schaltfläche in der Mitte, die die Schriftart der JMenuBar-Komponenten aktualisieren sollte, wenn sie geklickt wird. Um dies zu tun, feuert eine Methode setMyFont in einem ActionListener auf dem JButton. Nach mehreren aufgelisteten Versuchen habe ich es jedoch nicht geschafft, aber ich weiß nicht warum. Der verwendete Code in setMyFont unterAktualisieren Sie JMenu und JMenu Schriftart, nachdem JMenuBar sichtbar ist

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

Gibt es einen Grund, dass die Schrift nicht mit dem aktuellen Code für die Komponenten nicht aktualisiert? Wie kann ich meinen Code ändern, damit die Schriftart die Komponenten aktualisieren kann, obwohl sie bereits erstellt wurden?


vollständigen Code für 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)); 
     } 
    } 
} 

Antwort

4
  1. Nachdem die Schriftart einstellen, müssen Sie jede Komponente in der Hierarchie Anruf Update, um es UI ist - SwingUtilities eine bequeme Methode für dieses

    hat
    UIManager.put("Menu.font", menuFont); 
    SwingUtilities.updateComponentTreeUI(Main.this); 
    
  2. Verwenden Sie die FontUIResource Klasse zB

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

Der folgende Code aus dem entsandten SSCCE angepasst funktioniert für mich:

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+) Mit dem updateComponentTree (...) ist einfacher, als Sie Ihre eigene rekursive Methode Schreiben aller Komponenten in der Menüleiste hinzugefügt zu bekommen. Sie sollten nur die Methode in der Menüleiste aufrufen müssen, nicht den Frame. – camickr

+0

@camickr RE Aufruf in der Menüleiste, entsprechend der [docs] (https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html#programmatic), 'Aufruf der SwingUtilities updateComponentTreeUI Methode einmal pro '[Container der obersten Ebene] (https://docs.oracle.com/javase/tutorial/uiswing/components/topelvel.html) – copeg

+0

@copeg Vielen Dank für die Antwort. Leider mache ich es wahrscheinlich falsch, 'SwingUtilities.updateComponentTreeUI (Main.this);' aufzurufen, nachdem ich die Schriftarten eingestellt habe, tut nichts. Sollte ich außerhalb der 'setMyFont'-Funktion arbeiten oder sollte es funktionieren?* Ich habe auch 'FontUIResource' implementiert, es hat keinen Unterschied gemacht * – Dan

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

Ihre Action nicht in der Menüleiste arbeitet, die Sie mit dem Rahmen hinzugefügt.

sollte der Code sein:

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

Die getComponents() Methode nicht rekursiv ist. Ihre Schleife wird nur die JMenu-Komponenten erhalten, die der JMenuBar hinzugefügt werden, nicht die JMenuItems.

Auch wenn Sie Ihre Schriftarten erstellen, warum verwenden Sie nicht eine größere Schriftgröße, so dass Sie tatsächlich sehen können, wenn sich etwas ändert.

Wenn Sie die UIManager Font-Eigenschaften festlegen, bevor Sie die Komponenten erstellen, wird der Zweck der Schaltfläche ebenfalls in Ihrem veröffentlichten Code nicht erfüllt. Ihre Menüs sind bereits die gewünschte Schriftart.

1

Vielleicht können Sie versuchen, diese:

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