Wie lässt sich eine Programm-Menuleiste in das MacOS-Menu integrieren?
Die Klasse des Beispiels definiert einen kleinen leeren
JFrame
mit einer einfachen Menuleiste, die
einen Menupunkt zum Beenden der Applikation
enthält. Bei Betätigung von 'About' und
'Preferences' im Menu wird zur Demonstration jeweils
eine Nachricht auf der Konsole ausgegeben.
Die eigentliche Integration des Programm-eigenen Menus in die MacOS-Menuleiste erfolgt über den folgenden Eintrag in die System-Eigenschaften (43). Der Aufruf sollte möglichst früh im Quelltext erfolgen.
System.getProperties().put("apple.laf.useScreenMenuBar", "true");
ab v.9Das im Folgenden notierte Beispiel demonstriert wie ein programmeigener 'Über'- und ein 'Optionen'-Dialog ab der Java-Version 9 in das Apple-Menu eingebunden werden können.
import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.SwingUtilities; import java.awt.Desktop; import java.awt.desktop.AboutEvent; import java.awt.desktop.AboutHandler; import java.awt.desktop.PreferencesEvent; import java.awt.desktop.PreferencesHandler; import java.awt.desktop.QuitEvent; import java.awt.desktop.QuitHandler; import java.awt.desktop.QuitResponse; public class MacMenuLeiste { public MacMenuLeiste() { init(); } private void init() { if (getOS().equals("mac")) { new MacImpl(); } JMenuBar mBar = new JMenuBar(); JMenu fileMenu = new JMenu("Datei"); JMenuItem quitItem = new JMenuItem("Beenden"); quitItem.addActionListener(e -> System.exit(0)); fileMenu.add(quitItem); mBar.add(fileMenu); JFrame frame = new JFrame("Apple Menuleiste"); frame.setJMenuBar(mBar); frame.setSize(300, 300); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } public static void main(String[] args) { if (getOS().equals("mac")) { System.getProperties().put("apple.laf.useScreenMenuBar", "true"); } SwingUtilities.invokeLater(() -> new MacMenuLeiste()); } public static String getOS() { String osname = System.getProperty("os.name"); if (osname != null && osname.toLowerCase().indexOf("mac") != -1) { return "mac"; } if (osname != null && osname.toLowerCase().indexOf("windows") != -1) { return "win"; } return "noarch"; } } class MacImpl implements AboutHandler, PreferencesHandler, QuitHandler { public MacImpl() { handleOS(); } public void handleOS() { try { final Desktop desktop = Desktop.getDesktop(); desktop.setAboutHandler(this); desktop.setPreferencesHandler(this); desktop.setQuitHandler(this); } catch (Throwable e) { e.printStackTrace(); } } @Override public void handleAbout(AboutEvent arg0) { // new AboutDialog(); System.out.println("handleAbout()"); } @Override public void handlePreferences(PreferencesEvent arg0) { // new OptionsDialog(); System.out.println("handlePreferences()"); } @Override public void handleQuitRequestWith(QuitEvent arg0, QuitResponse arg1) { System.exit(0); } }
Im Rahmen eines Strategy-Pattern
wird zur Laufzeit in der Methode getOS()
(48)
das Betriebssystem abgefragt. Handelt es sich um ein
MacOSX, so wird eine Instanz der Klasse MacImpl
erzeugt (60). Sie implementiert drei Schnittstellen, die
jeweils eine Methode bereitstellen. Sie werden
überschrieben, um die zugehörige Funktionalität zu
erreichen (79, 85, 91). Aufgerufen werden sie auf einem
Objekt der Klasse Desktop
innerhalb von handleOS()
(67).
bis v.8Bis zur Version 8
findet man alle identisch benannten Interfaces und die
abweichend benötigte Klasse Application
,
deren diesbezügliche Funktion Desktop
übernommen hat, im package com.apple.eawt
.
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import com.apple.eawt.AboutHandler;
import com.apple.eawt.AppEvent.AboutEvent;
import com.apple.eawt.AppEvent.PreferencesEvent;
import com.apple.eawt.AppEvent.QuitEvent;
import com.apple.eawt.Application;
import com.apple.eawt.PreferencesHandler;
import com.apple.eawt.QuitHandler;
import com.apple.eawt.QuitResponse;
public class MacMenuLeiste {
public MacMenuLeiste() {
init();
}
private void init() {
if (getOS().equals("mac")) {
new MacImpl();
}
JMenuBar mBar = new JMenuBar();
JMenu fileMenu = new JMenu("Datei");
JMenuItem quitItem = new JMenuItem("Beenden");
quitItem.addActionListener(e -> System.exit(0));
fileMenu.add(quitItem);
mBar.add(fileMenu);
JFrame frame = new JFrame("Apple Menuleiste");
frame.setJMenuBar(mBar);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
if (getOS().equals("mac")) {
System.getProperties().put("apple.laf.useScreenMenuBar", "true");
}
SwingUtilities.invokeLater(() -> new MacMenuLeiste());
}
public static String getOS() {
String osname = System.getProperty("os.name");
if (osname != null && osname.toLowerCase().indexOf("mac") != -1) {
return "mac";
}
if (osname != null && osname.toLowerCase().indexOf("windows") != -1) {
return "win";
}
return "noarch";
}
}
class MacImpl implements ClassSelector, AboutHandler, PreferencesHandler,
QuitHandler {
public MacImpl() {
handleOS();
}
public void handleOS() {
try {
final Application application = Application.getApplication();
application.setAboutHandler(this);
application.setPreferencesHandler(this);
application.setQuitHandler(this);
} catch (Throwable e) {
System.err.println("setupMacOSXApplicationListener failed: "
+ e.getMessage());
}
}
public void handleAbout(AboutEvent arg0) {
// new AboutDialog();
System.out.println("handleAbout()");
}
public void handlePreferences(PreferencesEvent arg0) {
// new OptionsDialog();
System.out.println("handlePreferences()");
}
public void handleQuitRequestWith(QuitEvent arg0, QuitResponse arg1) {
System.exit(0);
}
}
interface ClassSelector {
public void handleOS();
}
Sollte Eclipse beim Zugriff auf die Klassen des Package
com.apple.eawt
einen Fehler anzeigen, so
muss eine Zugriffs-Regel
erstellt werden. Hierzu werden als 'Resolution'
'Accessible' und als 'Rule Pattern' 'com/apple/eawt/**'
eingetragen.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.