Hallo,
ich weiß, dass Tom sowas schon mal gepostet hat. Aber ich dachte, ich schreib es mal mit dem SAX-Parser und erweitere es ein wenig.
Da es teilweise Standard ist, dass die meisten Menu-Punkte auch in einer Toolbar enthalten sind, wird hier auch die Möglichkeit gegeben, eine Menupunkte mit in eine Toolbar zu übernehmen. Dazu muss man nur den toolbar-schalter in der XML-File setzen.
Zusätlich können auch Mnemonics(Unterstrichene Buchstaben im Menu) und Acceleratoren(z.b. STRG+S) gesetzt werden. Allerdings müssen bei den Acceleratoren die englische Namen der Tasten verwendet werden (Strg -> CTRL). Zusätlich hab ich ein Schema-File geschrieben. Gegen dieses File wird die XML-File validiert, um sicherzustellen, dass die XML-File auch richtig aufgebaut ist.
Schaut es auch einfach mal an.
Das ist das Schemafile (menu.xsd)
Man kann für jeden Menüpunkt eine eigene Action schreiben oder für Gruppen oder alle die gleiche Action nehmen.
Für Anregungen und Verbesserungsvorschläge bin ich dankbar.
Die nächsten Tage werde ich das gleiche mal für SWT posten.
MFG
zEriX
ich weiß, dass Tom sowas schon mal gepostet hat. Aber ich dachte, ich schreib es mal mit dem SAX-Parser und erweitere es ein wenig.
Da es teilweise Standard ist, dass die meisten Menu-Punkte auch in einer Toolbar enthalten sind, wird hier auch die Möglichkeit gegeben, eine Menupunkte mit in eine Toolbar zu übernehmen. Dazu muss man nur den toolbar-schalter in der XML-File setzen.
Zusätlich können auch Mnemonics(Unterstrichene Buchstaben im Menu) und Acceleratoren(z.b. STRG+S) gesetzt werden. Allerdings müssen bei den Acceleratoren die englische Namen der Tasten verwendet werden (Strg -> CTRL). Zusätlich hab ich ein Schema-File geschrieben. Gegen dieses File wird die XML-File validiert, um sicherzustellen, dass die XML-File auch richtig aufgebaut ist.
Schaut es auch einfach mal an.
Java:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JToolBar;
import de.tutorials.menu.MenuCtrl;
public class MenuExample extends JFrame {
public MenuExample() {
super("MenuExample");
setSize(300,300);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MenuCtrl menuCtrl = new MenuCtrl();
try {
menuCtrl.createMenuBar("mymenu.xml");
} catch (Exception e) {
e.printStackTrace();
}
JToolBar toolbar = menuCtrl.getToolBar();
toolbar.setFloatable(false);
setJMenuBar(menuCtrl.getMenuBar());
add(toolbar,BorderLayout.NORTH);
}
public static void main(String[] args) {
new MenuExample().setVisible(true);
}
}
Java:
package de.tutorials.menu;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import javax.swing.JMenuBar;
import javax.swing.JToolBar;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
public class MenuCtrl {
private JMenuBar menubar = null;
private JToolBar toolbar = null;
public JMenuBar getMenuBar() {
return menubar;
}
public JToolBar getToolBar() {
return toolbar;
}
public void createMenuBar(String file) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File("menu.xsd"));
factory.setValidating(false);
factory.setNamespaceAware(true);
factory.setSchema(schema);
SAXParser parser = factory.newSAXParser();
SwingMenuDocHandler handler = new SwingMenuDocHandler();
parser.parse(new File(file), handler);
menubar = handler.getMenuBar();
toolbar = handler.getToolBar();
}
}
Java:
package de.tutorials.menu;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class SwingMenuDocHandler extends DefaultHandler {
private final String EL_MENU = "menu";
private final String EL_MENU_ITEM = "menuItem";
private final String EL_SEPARATOR = "separator";
private final String EL_ACTION_LISTENER = "actionListener";
private final String ATT_TOOLBAR = "toolbar";
private final String ATT_ACCELERATOR = "accelerator";
private final String ATT_MNEMONIC = "mnemonic";
private final String ATT_ICON = "icon";
private final String ATT_ACTION = "action";
private final String ATT_TEXT = "text";
private JMenuBar bar = null;
private JToolBar toolbar = null;
private JButton toolbutton = null;
private JMenuItem item = null;
private ArrayList<JMenu> menus = new ArrayList<JMenu>();
private HashMap<String, ActionListener> listeners = new HashMap<String, ActionListener>();
private ImageIcon icon = null;
private String text = null;
private String action = null;
private int last = -1;
boolean hasAction = false;
public void endDocument() throws SAXException {
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equals(EL_MENU)) {
if (last > 0) {
menus.get(last - 1).add(menus.get(last));
} else
bar.add(menus.get(last));
menus.remove(last);
last--;
} else if (qName.equals(EL_MENU_ITEM)) {
toolbutton = null;
item = null;
icon = null;
action = null;
} else if (qName.equals(EL_ACTION_LISTENER)) {
hasAction = false;
}
}
public void startDocument() throws SAXException {
bar = new JMenuBar();
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if (qName.equals(EL_MENU)) {
String icon = atts.getValue(ATT_ICON);
JMenu menu = new JMenu(atts.getValue(ATT_TEXT));
menu.setMnemonic(getKeyEvent(atts.getValue(ATT_MNEMONIC)));
if(icon != null)
menu.setIcon(new ImageIcon(icon));
menus.add(menu);
last++;
} else if (qName.equals(EL_MENU_ITEM)) {
addMenuItem(atts);
if (new Boolean(atts.getValue(ATT_TOOLBAR)).booleanValue()) {
addToolbarButton(atts);
}
} else if (qName.equals(EL_ACTION_LISTENER)) {
hasAction = true;
} else if (qName.equals(EL_SEPARATOR)) {
menus.get(last).addSeparator();
}
}
public JMenuBar getMenuBar() {
return bar;
}
public JToolBar getToolBar() {
return toolbar;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (hasAction) {
String text = new String(ch, start, length);
text = text.trim();
try {
ActionListener listener = null;
if (listeners.containsKey(text)) {
listener = listeners.get(text);
} else {
listener = (ActionListener) Class.forName(text)
.newInstance();
listeners.put(text, listener);
}
item.addActionListener(listener);
if (toolbutton != null) {
toolbutton.addActionListener(listener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void error(SAXParseException e) throws SAXException {
System.out.println(e.getLineNumber());
e.printStackTrace();
throw new SAXException("XML-Datei entspricht nicht dem Schema");
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
throw new SAXException("XML-Datei entspricht nicht dem Schema");
}
@Override
public void warning(SAXParseException e) throws SAXException {
super.warning(e);
}
private void addMenuItem(Attributes atts) {
text = atts.getValue(ATT_TEXT);
String iconPath = atts.getValue(ATT_ICON);
if (iconPath != null)
icon = new ImageIcon(iconPath);
action = atts.getValue(ATT_ACTION);
item = new JMenuItem();
item.setText(text);
if (icon != null) {
item.setIcon(icon);
}
item.setActionCommand(action);
item.setMnemonic(getKeyEvent(atts.getValue(ATT_MNEMONIC)));
item.setAccelerator(getKeyStroke(atts.getValue(ATT_ACCELERATOR)));
menus.get(last).add(item);
}
private void addToolbarButton(Attributes atts) {
if (toolbar == null) {
toolbar = new JToolBar();
}
toolbutton = new JButton();
if (icon != null) {
toolbutton.setIcon(icon);
} else {
toolbutton.setText(text);
}
toolbutton.setToolTipText(text);
toolbutton.setActionCommand(action);
toolbutton.setMargin(new Insets(0, 0, 0, 0));
toolbutton.setBorderPainted(false);
toolbutton.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
if (((JButton) e.getSource()).isEnabled()) {
((JButton) e.getSource()).setBorderPainted(true);
}
}
public void mouseExited(MouseEvent e) {
if (((JButton) e.getSource()).isEnabled()) {
((JButton) e.getSource()).setBorderPainted(false);
}
}
});
toolbar.add(toolbutton);
}
private int getKeyEvent(String s) {
if (s != null && !s.equals("")) {
String keyEvent = "VK_" + s.toUpperCase();
try {
Field f = KeyEvent.class.getField(keyEvent);
return f.getInt(null);
} catch (Exception e) {
e.printStackTrace();
}
}
return KeyEvent.VK_UNDEFINED;
}
private KeyStroke getKeyStroke(String s) {
if (s != null && !s.equals("")) {
int i = s.indexOf('+');
if (i == -1) {
i = s.indexOf('-');
}
if (i == -1) {
return KeyStroke.getKeyStroke(getKeyEvent(s),
KeyEvent.VK_UNDEFINED);
}
String s1 = s.substring(i + 1);
String actionEvent = s.substring(0, i).toUpperCase() + "_MASK";
try {
Field f = ActionEvent.class.getField(actionEvent);
return KeyStroke.getKeyStroke(getKeyEvent(s1), f.getInt(null));
} catch (Exception e) {
}
}
return null;
}
}
Java:
package de.tutorials.actions;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class MenuAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if(action.equals("file.save")){
System.out.println("Save");
}
else if(action.equals("file.exit")){
System.exit(0);
}
}
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<menubar xmlns="http://www.home.org/menu" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.home.org/menu menu.xsd ">
<menu text="Datei">
<menuItem text="Speichern" action="file.save" icon="disk.png" mnemonic="s" accelerator="ctrl+s" toolbar="true">
<actionListener>de.tutorials.actions.MenuAction</actionListener>
</menuItem>
<separator/>
<menuItem text="Beenden" action="file.exit" icon="door_in.png">
<actionListener>de.tutorials.actions.MenuAction</actionListener>
</menuItem>
</menu>
</menubar>
Das ist das Schemafile (menu.xsd)
XML:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.home.org/menu"
xmlns:tns="http://www.home.org/menu" elementFormDefault="qualified">
<attributeGroup name="menuAttributes">
<attribute name="text" type="tns:estring" use="required"/>
<attribute name="mnemonic" type="tns:mstring" use="optional"/>
<attribute name="icon" type="tns:estring" use="optional"/>
</attributeGroup>
<attributeGroup name="menuItemExtension">
<attribute name="action" type="tns:estring" use="required"/>
<attribute name="toolbar" type="boolean" use="optional"/>
<attribute name="accelerator" type="tns:estring" use="optional"/>
</attributeGroup>
<group name="menuItemMenuGroup">
<choice>
<element name="menuItem" type="tns:menuItemType"/>
<element name="menu" type="tns:menuType"/>
</choice>
</group>
<group name="menuItemGroup">
<sequence>
<element name="separator" type="tns:separatorType"/>
<group ref="tns:menuItemMenuGroup" />
</sequence>
</group>
<complexType name="menubarType">
<sequence>
<element name="menu" type="tns:menuType" minOccurs="1" maxOccurs="unbounded"> </element>
</sequence>
</complexType>
<complexType name="menuType">
<sequence>
<group ref="tns:menuItemMenuGroup"/>
<choice minOccurs="0" maxOccurs="unbounded">
<group ref="tns:menuItemMenuGroup"/>
<group ref="tns:menuItemGroup" minOccurs="0" maxOccurs="unbounded"> </group>
</choice>
</sequence>
<attributeGroup ref="tns:menuAttributes"/>
</complexType>
<complexType name="menuItemType">
<sequence>
<element name="actionListener" type="tns:estring" minOccurs="0" maxOccurs="unbounded" />
</sequence>
<attributeGroup ref="tns:menuAttributes"/>
<attributeGroup ref="tns:menuItemExtension"/>
</complexType>
<complexType name="separatorType"> </complexType>
<simpleType name="estring">
<restriction base="string">
<minLength value="1"/>
</restriction>
</simpleType>
<simpleType name="mstring">
<restriction base="string">
<minLength value="1"/>
<maxLength value="1"/>
</restriction>
</simpleType>
<element name="menubar" type="tns:menubarType"/>
</schema>
Man kann für jeden Menüpunkt eine eigene Action schreiben oder für Gruppen oder alle die gleiche Action nehmen.
Für Anregungen und Verbesserungsvorschläge bin ich dankbar.
Die nächsten Tage werde ich das gleiche mal für SWT posten.
MFG
zEriX
Zuletzt bearbeitet von einem Moderator: