JMenu ändert nicht LookAndFeel

Ich habe eine Frage, ich habe eine Swing-Anwendung geschrieben. Beim ändern des LookAndFeels ändert sich aber die Menüleiste nicht.
Sieht jemand den Fehler?

package gui;

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

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.border.SoftBevelBorder;

public class MenuBar extends JMenuBar {

	public MenuBar(final MainFrame mf) {
		this.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED));
		this.setBackground(new Color(210,210,210));
		JMenu fileMenu = new JMenu("Datei");
		fileMenu.setFont(new Font("SansSerif",Font.PLAIN,14));
		this.add(fileMenu);
		JMenu viewMenu=new JMenu("Ansicht");
		this.add(viewMenu);
		viewMenu.setFont(new Font("SansSerif",Font.PLAIN,14));
		JMenu extraMenu=new JMenu("Extras");
		this.add(extraMenu);
		extraMenu.setFont(new Font("SansSerif",Font.PLAIN,14));
		JMenu helpMenu = new JMenu("Hilfe");
		this.add(helpMenu);
		helpMenu.setFont(new Font("SansSerif",Font.PLAIN,14));
		// Icon Size 24x24
		// fileMenu
		JMenuItem exitItem=new JMenuItem("Beenden");
		final Icon exitIcon=new ImageIcon("img/application-exit-2.png");
		exitItem.setIcon(exitIcon);
		exitItem.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				System.exit(0);
			}
		});
		fileMenu.add(exitItem);
		// viewMenu
		JMenuItem themeItem=new JMenuItem("Theme");
		final Icon themeIcon=new ImageIcon("img/games-config-background.png");
		themeItem.setIcon(themeIcon);
		themeItem.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				ThemeOptionPane top=new ThemeOptionPane(mf);
			}
		});
		viewMenu.add(themeItem);
		// extraMenu
		
		// helpMenu
		final Icon infoIcon=new ImageIcon("img/dialog-information-4.png");
		JMenuItem infoItem=new JMenuItem("Info");
		infoItem.setIcon(infoIcon);
		infoItem.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				JOptionPane.showMessageDialog(null, 
						"Dieses Programm wurde von Daniel Ritter entwickelt!", 
						"Info", 
						JOptionPane.INFORMATION_MESSAGE, 
						infoIcon);
			}
		});
		helpMenu.add(infoItem);
	}
}

Hier ist die Hauptfensterklasse:

package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.ScrollPane;
import java.awt.Toolkit;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.SoftBevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import res.ResLinker;

public class MainFrame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private MenuBar mb;
	private JPanel mainPanel;
	private JScrollPane jsp;
	private JTextPane jtp;
	private TabbedPane tabbedPane ;

	static SimpleAttributeSet DEFAULT = new SimpleAttributeSet();
	static SimpleAttributeSet EXCEPTION = new SimpleAttributeSet();

	static {
		StyleConstants.setForeground(DEFAULT, Color.blue);
		StyleConstants.setFontFamily(DEFAULT, "Courier");
		StyleConstants.setFontSize(DEFAULT, 12);

		StyleConstants.setForeground(EXCEPTION, Color.red);
		StyleConstants.setFontFamily(EXCEPTION, "Courier");
		StyleConstants.setFontSize(EXCEPTION, 12);
	}

	public MainFrame() {
		ResLinker rl = new ResLinker();
		rl.checkTheme();
		this.setSize(Toolkit.getDefaultToolkit().getScreenSize());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Toolkit.getDefaultToolkit().setDynamicLayout(true);
		this.setTitle(rl.getTitle());
		this.setJMenuBar(mb= new MenuBar(this));
		this.setIconImage(new ImageIcon("img/java.png").getImage());
		this.setLayout(new BorderLayout(5, 5));
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.add(mainPanel=new JPanel(), BorderLayout.PAGE_START);
		mainPanel.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED));
		mainPanel.add(tabbedPane=new TabbedPane());
		mainPanel.setPreferredSize(new Dimension(Toolkit.getDefaultToolkit()
				.getScreenSize().width , Toolkit.getDefaultToolkit()
				.getScreenSize().height * 74/ 100));
		tabbedPane.setPreferredSize(new Dimension(Toolkit.getDefaultToolkit()
				.getScreenSize().width , Toolkit.getDefaultToolkit()
				.getScreenSize().height * 74/ 100));
		jtp = new JTextPane();
		jtp.setEditable(false);
		jtp.setBackground(Color.WHITE);
		jtp.setForeground(Color.BLUE);
		jtp.setMinimumSize(new Dimension(Toolkit.getDefaultToolkit()
				.getScreenSize().width, Toolkit.getDefaultToolkit()
				.getScreenSize().height * 12 / 100));
		jsp = new JScrollPane();
		jsp.setPreferredSize(new Dimension(Toolkit.getDefaultToolkit()
				.getScreenSize().width, Toolkit.getDefaultToolkit()
				.getScreenSize().height * 14 / 100));
		jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		jsp.setBorder(new BevelBorder(BevelBorder.LOWERED));
		jsp.add(jtp);
		jsp.setViewportView(jtp);
		this.add(jsp, BorderLayout.PAGE_END);
		jtp.requestFocusInWindow();
		this.setVisible(true);
		
	}

	public void writeProtocoll(String s) {
		appendText("
" + s, DEFAULT);
	}

	public void writeExceptionProtocoll(String s) {
		appendText("
" + s, EXCEPTION);
	}

	private void appendText(String text, SimpleAttributeSet set) {
		try {
			jtp.getDocument().insertString(jtp.getDocument().getLength(), text,
					set);
			jtp.setCaretPosition(jtp.getDocument().getLength());

		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

}

Ich sehe hier nirgendwo die Änderung deines Look and Feels. Versuch ein KSKB zu erstellen.

So hier kommen die restlichen Klassen
Mit ResLinker frage ich unter anderem XML-Daten ab, wenn er das LookAndFeel vom letzten mal abfragt wird dieses gesetzt.


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.jdom2.*;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;


public class ResLinker {
	private SAXBuilder saxb;
	private Document doc;
	
	public ResLinker(){
		saxb=new SAXBuilder();
		try {
			doc =saxb.build(new File("container.xml"));
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public String getProgramName(){
		String s=doc.getRootElement().getChild("program").getText();
		return s;
	}
	public String getVersion(){
		String s=doc.getRootElement().getChild("version").getText();
		return s;
	}
	public String getTitle(){
		String s=doc.getRootElement().getChild("titel").getText();
		return s;
	}
	public  String getFunction(){
		String s=doc.getRootElement().getChild("function").getText();
		return s;
	}
	private  String getStyle(){
		String s=doc.getRootElement().getChild("style").getText();
		return s;
	}

	public void checkTheme(){
			if(this.getStyle().equals("System")){
				this.setSystemTheme();
				//UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			}else if(this.getStyle().equals("Nimbus")){
				this.setNimbusTheme();
				//UIManager.setLookAndFeel( "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
			}else if(this.getStyle().equals("Metal")){
				this.setMetalTheme();
				//UIManager.setLookAndFeel( "javax.swing.plaf.metal.MetalLookAndFeel");
			}else if(this.getStyle().equals("Motif")){
				this.setMotifTheme();
				//UIManager.setLookAndFeel( "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
			}else if(this.getStyle().equals("Synth")){
				this.setSynthTheme();
				//UIManager.setLookAndFeel( "javax.swing.plaf.synth.SynthLookAndFeel");
			}else{
				try {
					UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}	
		
	}
	
	public void setSystemTheme(){
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			this.defineTheme("System");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void setNimbusTheme(){
		try {
			UIManager.setLookAndFeel( "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
			this.defineTheme("Nimbus");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void setMetalTheme(){
		try {
			UIManager.setLookAndFeel( "javax.swing.plaf.metal.MetalLookAndFeel");
			this.defineTheme("Metal");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void setMotifTheme(){
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
			this.defineTheme("Motif");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void setSynthTheme(){
		try {
			UIManager.setLookAndFeel("javax.swing.plaf.synth.SynthLookAndFeel");
			this.defineTheme("Synth");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	private void defineTheme(String theme){
		XMLOutputter xmlOutput = new XMLOutputter();
		doc.getRootElement().getChild("style").setText(theme);
		xmlOutput.setFormat(Format.getPrettyFormat());
		try {
			xmlOutput.output(doc, new FileWriter("container.xml"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
}```
Mit dem ThemeOptionPane kann ein LookAndFeel deiner Wahl ausgewählt werden, welches dann gesetzt wird.

package gui;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import res.ResLinker;

public class ThemeOptionPane extends JOptionPane {

public ThemeOptionPane(MainFrame mf){
	ResLinker rl=new ResLinker();
	String[] themes={"System","Nimbus","Metal","Motif"/*,"Synth"*/};
	String s=(String)JOptionPane.showInputDialog(null,
			"Bitte das gewünschte Theme wählen","Theme",
			JOptionPane.QUESTION_MESSAGE, null,
			themes,themes[0]);
	if(s.equals("Nimbus")){
		rl.setNimbusTheme();
	}else if(s.equals("System")){
		rl.setSystemTheme();
	}else if(s.equals("Metal")){
		rl.setMetalTheme();
	}else if(s.equals("Motif")){
		rl.setMotifTheme();
	}/*else if(s.equals("Synth")){
		rl.setSynthTheme();
	}*/
	SwingUtilities.updateComponentTreeUI(mf.getContentPane());
}

}


ps. Ich bin davon ausgegangen das es an der Implementierung der JMenubar liegt das Sie als einzige nicht das LookAndFeel ändert.

*** Edit ***

Seltsamer Weise werden die Icons nach mehrmaligem wechseln des LookAndFeels doppelt dargestellt. Erkennt wer denn Wurm der da drin steckt?

Rufst du SwingUtilities.updateComponentTreeUI(frame); nachdem du das LnF änderst auf? Wenn nicht mach das mal.

Du hast mich auf die richtige Idee gebracht! Habe immer ‘SwingUtilities.updateComponentTreeUI(frame.getContentPane());’ das fasst aber die Menüleiste scheinbar nicht mit ein.
‘SwingUtilities.updateComponentTreeUI(frame);’ tut dies aber.

Natürlich, die Menüleiste ist Teil des Frames nicht des ContentPanes. Du setzt die JMenuBar ja auch direkt auf dem Frame, bei Komponenten kannst du höchstens ein PopupMenü hinzufügen.