前の項目でフォームのコンポーネントに結び付けられたswingモデルクラスにアクセスする方法がわかりました。 ここではボタン型のinputタグに結び付けられたmodelにActionListenerを登録し、name属性を表示するサンプルコードを示します。 対象のタイプはcheckbox、radio、image、resetとsubmitボタンです。
HTMLDocumentを調べる手順やタイミングは前の項目と同じです。 JEditorPaneのdocumentにDocumentListenerを登録し、changedUpdateでHTMLDocumentに収められたElementをチェックします。
Elementが持つAttributeSetにmodelが含まれていたら、そのElementはフォームのコンポーネントタグに結びついています。 AttributeSetからhtmlタグのname属性の値を調べてアクションコマンドに登録します。 この場合、AttributeSetには文字列で表すと「name」になるキーが2つあります。 1つはタグ名を表すnameで、属性値はHTML.Tagクラスのインスタンスです。 もう1つはhtmlタグに記述されたname属性です。 アクションコマンドに登録するのはこちらなので、HTML.Tag型の方は無視します。
private void checkAttributes(Element elem) { AttributeSet attrs = elem.getAttributes(); Enumeration attrNames = attrs.getAttributeNames(); Object model = null; String tagName = null; while(attrNames.hasMoreElements() ) { Object attrName = attrNames.nextElement(); Object attr = attrs.getAttribute(attrName); // model属性があるなら記録 if("model".equals(attrName.toString() ) ) { model = attr; } // htmlタグにname属性があるならば記録 else if(!(attr instanceof HTML.Tag) && "name".equals(attrName.toString() ) ) { tagName = attr.toString(); } } // elemにmodel属性があり、それがButtonModelクラスの場合 if(model instanceof ButtonModel) { ButtonModel buttonModel = (ButtonModel)model; buttonModel.addActionListener(this); buttonModel.setActionCommand(tagName); } // 他タイプのフォームコンポーネントを扱う場合 // else if(model instanceof PlainDocumentなど) ... }
今回はname属性を使いましたが、id属性やvalue属性でも同様にコーディングできます。
上の例ではButtonModelを対称にしたのでsetActionCommandでどのフォームコンポーネントがクリックされたか分かりました。 しかし他のコンポーネントの場合はもうひと工夫要ります。 例えば、リスナーにname属性を覚えさせるなどすると良いでしょう。 textareaにイベントを追加する場合は次のようなDocumentListenerを作ります。
class InputTextListener implements DocumentListener { private String _name; public InputTextListener(String name) { _name = name; } public String getName() { return _name; } ... overrideメソッド }
先程のcheckAttributesメソッドは次のようになります。
private void checkAttributes(Element elem) { AttributeSet attrs = elem.getAttributes(); Enumeration attrNames = attrs.getAttributeNames(); Object model = null; boolean isTextArea = false; String tagName = null; while(attrNames.hasMoreElements() ) { Object attrName = attrNames.nextElement(); Object attr = attrs.getAttribute(attrName); // model属性があるなら記録 if("model".equals(attrName.toString() ) ) { model = attr; } // htmlタグがtextareaかチェック else if(attr == HTML.Tag.TEXTAREA) { isTextArea = true; } // htmlタグにname属性があるならば記録 else if(!(attr instanceof HTML.Tag) && "name".equals(attrName.toString() ) ) { tagName = attr.toString(); } } // elemにmodel属性があり、それがPlainDocumentクラスの場合 if(isTextArea && (model instanceof PlainDocument) ) { PlainDocument inputDoc = (PlainDocument)model; InputTextListener listener = new InputTextListener(tagName); inputDoc.addDocumentListener(listener); } }
以下はサンプルコードの全文です。 htmlファイルなどはネタのトップからダウンロードしてください。
// ModelTest.java import java.io.File; import java.net.URL; import java.util.Enumeration; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.text.html.*; public class ModelTest extends JFrame implements DocumentListener, ActionListener { public static final String TEST_HTML = "jeditorpane_test.html"; public static final String TEST_CSS = "jeditorpane_test.css"; private JEditorPane _editorPane; public ModelTest() { setDefaultCloseOperation(EXIT_ON_CLOSE); try { _editorPane = new JEditorPane(); _editorPane.setEditable(false); _editorPane.setContentType("text/html"); HTMLEditorKit editorKit = (HTMLEditorKit)_editorPane.getEditorKit(); editorKit.setAutoFormSubmission(false); File cssFile = new File(TEST_CSS); editorKit.getStyleSheet().importStyleSheet(cssFile.toURI().toURL() ); _editorPane.setPage(new File(TEST_HTML).toURI().toURL() ); JScrollPane scrollPane = new JScrollPane(_editorPane); getContentPane().add(scrollPane); _editorPane.getDocument().addDocumentListener(this); } catch(Exception exc) { exc.printStackTrace(); } } public static void main(String[] args) { ModelTest app = new ModelTest(); app.setSize(640, 480); app.setVisible(true); } private void checkElements(Element elem) { checkAttributes(elem); int count = elem.getElementCount(); for(int i = 0; i < count; i++) { checkElements(elem.getElement(i) ); } } private void checkAttributes(Element elem) { AttributeSet attrs = elem.getAttributes(); Enumeration attrNames = attrs.getAttributeNames(); Object model = null; String tagName = null; while(attrNames.hasMoreElements() ) { Object attrName = attrNames.nextElement(); Object attr = attrs.getAttribute(attrName); // model属性があるなら記録 if("model".equals(attrName.toString() ) ) { model = attr; } // htmlタグにname属性があるならば記録 else if(!(attr instanceof HTML.Tag) && "name".equals(attrName.toString() ) ) { tagName = attr.toString(); } } // elemにmodel属性があり、それがButtonModelクラスの場合 if(model instanceof ButtonModel) { ButtonModel buttonModel = (ButtonModel)model; buttonModel.addActionListener(this); buttonModel.setActionCommand(tagName); } // 他タイプのフォームコンポーネントを扱う場合 // else if(model instanceof PlainDocumentなど) ... } public void insertUpdate(DocumentEvent event) { } public void removeUpdate(DocumentEvent event) { } public void changedUpdate(DocumentEvent event) { Document doc = _editorPane.getDocument(); checkElements(doc.getDefaultRootElement() ); } public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); JOptionPane.showMessageDialog(this, "name = " + command); } }