XMLを使用してSwingでメニューバーを生成する

良い一日、親愛なるハブラフチアン。

最近、ほとんどすべての機能UIに存在する標準バーであるメニューバーを作成する問題に遭遇しました。 反対に、SwingでUIを作成することは作成が難しいという問題ではなく、ほとんどのインターフェイス要素は数行のコードで作成されます(これはメニューにも同様に適用されます)。 そして、多機能で複雑なメニューを作成するという問題があり、それは信じられないほどの量のコードに変換されます。



複雑なメニューを生成するプロセス全体を保存するために、XMLと呼ばれる力に頼ることにしました。 それを使用して、見たいようにメニューを記述することができます。そして、プレミアムではないユーティリティクラスのおかげで、XMLが解析され、その結果、すべての複雑なメニューを取得することができます。 興味のある方は、habrokatへようこそ...



そのため、最初に、UIにバインドするメニューについて説明します。 例として、私は私たちの多くがGoogleドキュメントで見たメニューに基づいて、少し切り捨てられたメニューを使用することにしました(Googleをご容赦ください)。



構造に加えて、説明されている要素の一部には、画像、キーボードショートカット、ニーモニックがあります。 こちらがシンプルなメニューで作成してみます。



XML形式のメニュー項目の説明



美しい、部分的に借用した(例としてのみ)メニューを記述するXMLファイルの作成を開始する前に、その中にどの要素が存在するかを確認しましょう。



まず第一に、これはJMenuBarです。これは、以下で説明する要素が配置されるパネルです。 そして、XML処理後にこのパネルを引き出します。



次に、JMenuの代表者-メニューとサブメニュー(ファイル、編集、段落スタイルなど)が続きます。 また、JMenuItem-すべてのメニューおよびサブメニューの要素(開く、コピー、貼り付け、不正使用の報告など)。 そしてもちろん、仕切り(セパレータ)は、メニュー項目が論理グループに結合される水平線です。



各要素には、-要素の名前(コードから目的の要素を参照するために使用できます)、テキスト、テキスト付近の画像の存在、キーボードを使用して要素に焦点を合わせることができるキーの組み合わせなど、いくつかのプロパティがありますニーモニック-名前の下線付き要素として表示され、alt + highlighted_character_nameの組み合わせで呼び出されます。たとえば、ファイルメニューを開くにはalt + F、キーボードショートカット(いわゆるアクセラレータ-はメニュー項目の隣のキーの組み合わせとして表示されますispo zovaniya、メニュー自体を入力しない。たとえば、Ctrlキー+ O)は、ファイルを開きます。 また、要素はアクティブと非アクティブにできます(テキストが選択されていない場合は、[編集]-> [切り取り])。



メニューを構成するレンガについて知りました。 上記の要素に対応するXMLタグとプロパティ名を考慮する必要があります。



タグ:JMenuBar-<menubar>、JMenu-<menu>、JMenuItem-<menuitem>、separator-<separator />



プロパティ:名前-名前、テキスト-テキスト、画像-イメージ、ニーモニック-ニーモニック、アクセラレータ-アクセラレータ、要素のアクセシビリティ-isEnabled。



メニューを記述するXMLをご覧ください!



メニューのXML要素を決定したら、すぐにメニューの説明に進むことができます。この説明を結果として取得します。



<?xml version="1.0" encoding="utf-8"?> <menubar name="ourMenu"> <!--File--> <menu name="file" text="File" mnemonic="F"> <menu name="new" text="New" mnemonic="N"> <menuitem name="doc" text="Document" image="./data/MenuXML/img1.jpg"/> </menu> <menuitem name="open" text="Open..." mnemonic="O" accelerator="control O"/> <separator/> <menu name="download" text="Download as"> <menuitem name="msword" text="Microsoft Word (.docx)"/> </menu> <separator/> <menuitem name="print" text="Print" mnemonic="P" accelerator="control P"/> </menu> <!--Edit--> <menu name="edit" text="Edit" mnemonic="d"> <menuitem name="undo" text="Undo" image="./data/MenuXML/img1.jpg" accelerator="control Z" isEnabled="false"/> <menuitem name="redo" text="Redo" image="./data/MenuXML/img1.jpg" accelerator="control Y" isEnabled="false"/> <separator/> <menuitem name="cut" text="Cut" image="./data/MenuXML/img1.jpg" accelerator="control X" isEnabled="false"/> <menuitem name="copy" text="Copy" image="./data/MenuXML/img1.jpg" accelerator="control C" isEnabled="false"/> <menuitem name="paste" text="Paste" image="./data/MenuXML/img1.jpg" accelerator="control V" isEnabled="false"/> </menu> <!--Format--> <menu name="format" text="Format" mnemonic="o"> <menu name="styles" text="Paragraph styles"> <menu name="normalText" text="Normal text"> <menuitem name="applyNormText" text="Apply normal text" accelerator="control alt 0"/> </menu> <menu name="heading" text="Heading"> <menuitem name="applyHeading" text="Apply heading" accelerator="control alt 1"/> </menu> <separator/> <menu name="options" text="Options" image="./data/MenuXML/img1.jpg"> <menuitem name="saveOptions" text="Save options"/> </menu> </menu> </menu> <!--Help--> <menu name="help" text="Help" mnemonic="H"> <menuitem name="issue" text="Report an issue"/> <menuitem name="abuse" text="Repor abuse"/> <separator/> <menuitem name="shortcuts" text="Keyboard shortcuts" accelerator="control SLASH"/> </menu> </menubar>
      
      





XMLハンドラー



メニューをXMLの一部として説明したので、それを解析するだけです。 XMLを操作するには、Javaパッケージorg.xml.saxを使用します(APIはこちらこちらにあります )。 DefaultHandlerクラスを拡張するXMLMenuHandlerクラスは、ContentHandlerインターフェイスと他の同様に有用なインターフェイスを実装し、XML構造の要素を処理します。



 public class XMLMenuHandler extends DefaultHandler { private Map menuMap = new HashMap(); private JMenuBar menuBar; private LinkedList menuList = new LinkedList(); @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { //   (menu, menubar, menuitem  separator) if(qName.equals("menu")) { parseMenu(atts); } else if(qName.equals("menubar")) { parseMenubar(atts); } else if(qName.equals("menuitem")) { parseMenuitem(atts); } else if(qName.equals("separator")) { parseSeparator(); } } //   </menu>      . @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(qName.equals("menu")) { menuList.removeFirst(); } } private void parseSeparator() { //     ((JMenu)menuList.getFirst()).addSeparator(); } private void parseMenuitem(Attributes atts) { //   JMenuItem menuItem = new JMenuItem(); String menuItemName = atts.getValue("name"); //   parseAttributes(menuItem, atts); menuMap.put(menuItemName, menuItem); //     ((JMenu)menuList.getFirst()).add(menuItem); } private void parseMenubar(Attributes atts) { //   JMenuBar tempMenuBar = new JMenuBar(); String menuBarName = atts.getValue("name"); menuMap.put(menuBarName, tempMenuBar); menuBar = tempMenuBar; } private void parseMenu(Attributes atts) { //  JMenu menu = new JMenu(); String menuName = atts.getValue("name"); //  parseAttributes(menu, atts); menuMap.put(menuName, menu); // ,     -. if (menuList.size() == 0) { menuBar.add(menu); } else { //  ((JMenu)menuList.getFirst()).add(menu); } //    - menuList.addFirst(menu); } private void parseAttributes(JMenuItem item, Attributes atts) { //  String text = atts.getValue("text"); String image = atts.getValue("image"); String mnemonic = atts.getValue("mnemonic"); String accelerator = atts.getValue("accelerator"); String isEnabled = atts.getValue("isEnabled"); //         XML item.setText(text); if(image != null) { item.setIcon(new ImageIcon(image)); } if(mnemonic != null) { item.setMnemonic(mnemonic.charAt(0)); } if(accelerator != null) { item.setAccelerator(KeyStroke.getKeyStroke(accelerator)); } if(isEnabled != null) { item.setEnabled(Boolean.parseBoolean(isEnabled)); } } public Map getMenuMap() { return menuMap; }
      
      







XMLの読み込みを担当するクラスを記述し、ハンドラーを積極的に使用します。



 public class XMLMenuParser { //XML,    private InputSource inputSource; //XML  private SAXParser saxParser; // XML  private XMLMenuHandler xmlMenuHandler; public XMLMenuParser(InputStream inputStream) { // XML    XML   . try { Reader reader = new InputStreamReader(inputStream); inputSource = new InputSource(reader); saxParser = SAXParserFactory.newInstance().newSAXParser(); xmlMenuHandler = new XMLMenuHandler(); } catch (Exception e) { System.out.println("Something went wrong during SAXParser initialization: " + e.getMessage()); throw new RuntimeException(e); } } public void parseXML() throws IOException, SAXException { saxParser.parse(inputSource, xmlMenuHandler); } public JMenuBar getMenuBar(String name) { return (JMenuBar)xmlMenuHandler.getMenuMap().get(name); } }
      
      







そして、実際に行われた作業を見てみましょう-XMLで説明されているメニューを単純なUIに適用します。



 public class XMLMenuCreator extends JFrame { public XMLMenuCreator() { super("XML Menu Creator"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); try { FileInputStream in = new FileInputStream("./data/MenuXML/menu.xml"); XMLMenuParser xmlParser = new XMLMenuParser(in); xmlParser.parseXML(); //,   XML  ,    ( <menubar>), //    UI setJMenuBar(xmlParser.getMenuBar("ourMenu")); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } setSize(200, 200); setVisible(true); } }
      
      







アプリケーションを起動すると、次のようなメニューのウィンドウが表示されます(その構造は上記と同じです)。

画像



おわりに



分岐メニューの構築が必要になった場合、メニューバーのすべての要素とそのプロパティを記述する適切なXMLファイルを作成し、XMLMenuHandlerとXMLMenuParserの2つのクラスをプロジェクトに接続するだけです(それらを組み合わせることができます) XMLMenuHandlerを内部クラスにすることにより)、上記の例に示すようにこのスープセットを使用します。



プログラマーの最終日、ご清聴ありがとうございました。



プロジェクトのソースコードは、 http//www.google.com/url?q = https%3A%2F%2Fdocs.google.com%2Fopen%3Fid%3D0B1I02TclzMD_RTVtNVFNVkkxU1Uにあります。



All Articles