Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

JEditorPaneでHTMLのFormを利用

JEditorPaneにHTMLを表示し、その中のFormのイベント処理をしたいのですが、うまくいきません。


株式会社カットシステム 大村忠史著
SwingによるJava GUIプログラミングIII
第7章の5

[Form3.java]

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.text.html.*;
import java.util.*;

public class Form3 extends JFrame {
    JEditorPane html;
    Vector formComponents = new Vector();
 
    String htmlText = 
      "<html><body><form action=aaa method=post>" +
      "名前: <input type=text name=$1 ><p>" + 
      "パスワード: <input type=password name=$2 ><p>" + 
      "コメント: <textarea rows=8 cols=40 name=$3 > 備考 </textarea><p>" +
      "選択1: <select name=$4><option value>aaaaa<option value>bbbbb<option value>cccc</select><p>" +
      "選択2: <select name=$5 size=2><option>aaaaa<option>bbbbb<option>cccc<option>ddddd</select><p>" +
      "ラジオボタン: <input type=radio name=$6 value>111 " +
      " <input type=radio name=$7 value>222 <p>" +
      "チェックボックス: <input type=checkbox name=$8 value>111 " +
      " <input type=checkbox name=$9 value>222 <p>" +
      " <input type=submit name=$10 value=OK> " +
      " <input type=reset name=$11 value=Cancel> " +
      "</form></body>" ;

  public static void main(String[] args) {
    Form3 frame = new Form3( "Form3" );
    frame.setDefaultCloseOperation(3); // EXIT_ON_CLOSE
    frame.setSize( 400, 600 );
    frame.setVisible( true );
  }
  Form3( String title ){
    super( title );
    Container pane = getContentPane();
    html = new JEditorPane( "text/html", htmlText );
    pane.add( html );

    Document doc = html.getDocument();
    getAction( doc.getDefaultRootElement() );
  }
  void getAction( Element e ){
    boolean submit = false;
    AttributeSet aSet = e.getAttributes();
    Enumeration enumration = aSet.getAttributeNames();
    String name = null;
    Object o = null;
    Object model = null;
    while( enumration.hasMoreElements() ){
      o = enumration.nextElement();
      Object v = aSet.getAttribute( o );
      if( o.toString().equals("name") && o instanceof HTML.Attribute ){
        name = v.toString();
      }
      if( o.toString().equals("type") && v.toString().equals("submit") ){
         submit = true;
      }
      if( submit && v instanceof DefaultButtonModel ){
        DefaultButtonModel button = (DefaultButtonModel)v;
        button.addActionListener( new CheckAction() );
      }
      else if( v instanceof DefaultButtonModel || v instanceof PlainDocument ){
        model = v;
      }
    }
    if( model != null ){
      formComponents.addElement( new FormComponent( name, model ) );
    }
    //--------- Element の階層を下へ再帰的に辿っていく
    for( int i = 0 ; i < e.getElementCount() ; i++ ) {
      getAction( e.getElement(i) );
    }
  }
  void getResult(){
    for( int i=0 ; i < formComponents.size() ; i++ ){
      FormComponent fc = (FormComponent)formComponents.elementAt(i);
      if( fc.model instanceof DefaultButtonModel ){
        DefaultButtonModel bt = (DefaultButtonModel)fc.model;
        fc.result = new Boolean( bt.isSelected() ).toString();
      }
      else if( fc.model instanceof PlainDocument ){
        PlainDocument doc = (PlainDocument)fc.model;
        try{
          fc.result = doc.getText( 0, doc.getLength() );
        }catch( BadLocationException ex ){
          System.out.println( ex );
        }
      }
    }
  }
  void showResult(){
    for( int i=0 ; i < formComponents.size() ; i++ ){
      FormComponent fc = (FormComponent)formComponents.elementAt(i);
      System.out.println( fc.name +" : "+ fc.result );
    }
  }

  class CheckAction implements ActionListener {
    public void actionPerformed( ActionEvent e ){
      getResult();
      html.setVisible(false);
      showResult();
    }
  }
  class FormComponent {
    String name;
    Object model;
    String result;
    FormComponent( String name, Object model ){
      this.name = name;
      this.model = model;
      result = "";
    }
  }
}

を参考に使用としたのですが、Form3自体OKボタンを押しても反応がありません。

どこを修正すればいいのか教えてください。

21

回答

3499

閲覧

21件の回答

評価

0

JEdtorPane のイベント範囲をまちがえてるとおもわれる。
JavaDocを確認すべし

評価

0

返信ありがとうございます。JavaDocを見るとはhttp://java.sun.com/javase/ja/6/docs/ja/api/index.htmlを見るということですよね?すいません、見ても分かりませんでした。

Form3.javaは上述の本に載っているソースそのまま(enumが識別子として使えなくなっていたのでenumrationに変えた以外は)なのですが、本の初板が1999年12月です。当時は使えたけどもう使えなくなったということでしょうか?

評価

0

訂正です。
見たのはJavaDocのhttp://java.sun.com/javase/ja/6/docs/ja/api/javax/swing/JEditorPane.htmlです。

評価

0

…普通に実行してみた。
何度か実行時は動作してなかったが、何度かあとでは実行された。
というかコンソールに表示された。


バグとして認識できる箇所が何箇所かあったので
書籍を書いた人の知識が疑えそう。

1.OKボタンを押下後に画面が真っ白になる。
2.SELECT タグの取得ができていない。
3.HTMLエディタが編集可能だ

ほかにも本腰いれてさがしたらでそうだなぁ

まあ、認識間違えHyperlinkListener 以外でも取得できるのね。

評価

0

すいません。やはりボタンを押しても何も起こりません。環境が悪いのでしょうか。

java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b06)
Java HotSpot(TM) Client VM (build 1.6.0_02-b06, mixed mode, sharing)

書籍のその章はHTML内のFormのイベント処理法について説明する実験的なプログラムが連なっており、そのためにバグとして認識できる箇所があるのだと思います。2番については7章の6で取得しています。

評価

0

実行、トレースしてみた限り、提示されたコードの以下のif文が真になることがありません。
if( submit && v instanceof DefaultButtonModel )

つまり、button.addActionListener( new CheckAction() );で、ボタンにActionListenerが登録されることがないです。よって、ボタン押下時にアクションが実行されないのです。

私が実行した環境は以下のとおり。
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

でも、杏さんは『何度か実行時は動作してなかったが、何度かあとでは実行された。』と仰っている(動作したのかどうか、分かりませんが。動作したと考えると)ので、
バージョンによって、HTMLParserの挙動が異なって、動作するのかもしれません。

評価

0

fooさん。
私も最初Listener が登録されていないからかとおもいました。

実際動作させてみると、HTMLのsubmitによりそのイベントは発生していました。

あとバグも見つけたというところから動作はしています。

swingGUI上で何かが発生するのではなく、コンソールにて結果が表示されているので、
画面真っ白になっていたらコンソールを確認してください。

動作環境では1.5準拠コンパイルでVM(ver 1.6.0u2)で動作させてたりします。

たぶん、Form3.javaの記述からみて
書籍のjava はたぶん 1.4.2 以前…

評価

0

>杏さん
ありがとうございます。
たしかに、1.5準拠コンパイルで上述の環境で動作させると、以下の条件文を通って、if( submit && v instanceof DefaultButtonModel)、button.addActionListener( new CheckAction() );が実行されますね。

さすがに動作をまったく確認せずに、本を出版することもないでしょうから、著者が書いた時点(VMのバージョンが1.5以前)では、期待したように動作していたのでしょう。
著者のコードのバグではなく、出版後のAPIのバグか仕様変更といったところでしょうか。

>カチノナさん
ということで、1.5でコンパイルしてみてください。

評価

0

>動作をまったく確認せずに、本を出版することもないでしょう
コンパイルエラー入りのコードを堂々と載せている書籍は、ないこともないですよ。

評価

0

>コンパイルエラー入りのコードを堂々と載せている書籍は、ないこともないですよ。
コンパイルエラーですか?
コンパイルエラーは、さすがにまずいでしょ。
それじゃあ、脳内コードじゃないですか。。。

評価

0

最初は動く状態で書いたのに、本になる間際になって「こうしたほうがいいな」とか、確認せずに手を入れたりしたんじゃないですかね。

評価

0

そんなものじゃ済まないものもあります。
まさに脳内コード。

評価

0

>最初は動く状態で書いたのに、本になる間際になって「こうしたほうがいいな」とか、確認せずに手を入れたりしたんじゃないですかね。

「出版」と「開発のリリース」を置き換えると、ありえそうな気がします。

>カチノナさん
ということで、APIのバグ、仕様変更、書籍のコード自体も疑った方がよい。ということでしょうか。
とりあえず、1.5でコンパイルして実行してみてください。

#この本の著者は、Swing黎明期(今もかもしれませんが)に、java-houseでSwingの第一人者みたいに言われてた人ですから、書籍のコードのバグではないと考えたいところですが、この情報も私の思考のフィルターになっているかもしれません。


評価

0

>適当さん
>そんなものじゃ済まないものもあります。

本題とずれてしまって申し訳ないです。
興味本位で聞きたいのですが、
コンパイルエラーより酷いものってどんなものですか?

評価

0

お返事ありがとうございます。

>fooさん
1.5でコンパイルして実行するときは
javac -target 1.5 -source 1.5 Form3.java
としたあと
java Form3
でいいのですよね?やはりOKボタンを押しても動かないのですが・・・。



>杏さん
本ではjava2 SDK 1.2.2 または JDK1.1.8+Swing1.1.1を前提にしているようです。

>mioさん,適当さん
出版されている物だからといって信じ切ってしまってはいけないのですね。勉強になります。

評価

0

明らかに言語そのものを理解していないコードとかです。
C++のコードなのにinterfaceとか出てきたり、そんな感じです。

あ、
#define interface struct
とか、そういうものじゃないです。念のため。

評価

0

>やはりOKボタンを押しても動かないのですが・・・。
button.addActionListener( new CheckAction() );は実行されますか。

>本ではjava2 SDK 1.2.2 または JDK1.1.8+Swing1.1.1を前提にしているようです。
では、書籍に責任を問うのは難しいでしょう。

>明らかに言語そのものを理解していないコードとかです。
すごい本もあるんですね。ちょっと読んでみたい気もします。そんなのでも出版ってできるんですねー。(自費出版ですか?)校閲とかどうなってるんだろう。

そういうのを『10日でおぼえる〜』、『初心者のための〜』、『0から始める〜』みたいな初心者向けの本でやったら、明らかにデスクリムゾン級の本認定ですね。
#デスクリムゾンを知らないかもしれませんが。

評価

0

      if (v instanceof DefaultButtonModel) {
          System.out.println(o);
      }

でやると、"model"が6つ出てきました。
ということは、どう頑張ってもaddActionListenerが発行されませんね。

ロジックそのものがおかしい気が。

評価

0

1.5モードでコンパイルしたものと、1.6でコンパイルしたものを実行して、パースしている内容を出力してdiffで比較すると、トレース結果が明らかに違う。。。

評価

0

>button.addActionListener( new CheckAction() );は実行されますか。

実行されていませんでした。。。

評価

0

なので、ロジックを見直して、バージョンを問わずに実行できるように修正するのが理想ですね。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。