前の項目でフォームのコンポーネントに結び付けられた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);
}
}