javax.swing.JEditorPane

目的
ローカルのHTMLファイルを表示する。

関連クラス

今回のソース
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.MalformedURLException;

class JEditorPaneDemo
{
	public static void main(String args[])
	{
		new MainWindow();
	}
}

class MainWindow extends JFrame
{
	// メンバ
	JEditorPane html_view;
	JTextField text_url;
	JComboBox encoding_list;
	File current_path = new File("");

	// 定数
	final String line_separator = System.getProperty("line.separator");
	final String file_separator = System.getProperty("file.separator");
	final String ENCODING_SJIS = "Shift_JIS";
	final String ENCODING_EUC  = "EUC-JP";

	public MainWindow()
	{
		super("Local HTML Viewer");
		setBackground(Color.white);

		// ウインドウリスナの追加
		WindowListener listener = new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		};
		addWindowListener(listener);

		// HTML表示部の構築
		html_view = new JEditorPane("text/html","<h1 align = \"center\">Html Viewer</h1>");
		html_view.setEditable(false);

		// ハイパーリンクリスナの追加
		HyperlinkListener listener_html_view = new HyperlinkListener()
		{
			public void hyperlinkUpdate(HyperlinkEvent e)
			{
				if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
				{
					File link_target = new File(current_path.getAbsolutePath() + file_separator + e.getDescription());
					html_view.setText(getTextFromFile(link_target));
					try
					{
						text_url.setText(link_target.toURL().toString());
					}
					catch(MalformedURLException me)
					{
						System.err.println(me);
					}
				}
			}
		};
		html_view.addHyperlinkListener(listener_html_view);

		// ファイルを開くボタンの追加
		JButton button_open = new JButton("Open");
		ActionListener listener_button_open = new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				// ファイルを開くダイアログの表示
				JFileChooser file_choose = new JFileChooser(current_path);
				if(file_choose.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION)
				{
					File file = file_choose.getSelectedFile();
					current_path = new File(file.getParent());

					html_view.setText(getTextFromFile(file));
					try
					{
						text_url.setText(file.toURL().toString());
					}
					catch(MalformedURLException me)
					{
						System.err.println(me);
					}
				}
			}
		};
		button_open.addActionListener(listener_button_open);

		// URL表示部の追加
		text_url = new JTextField(30);
		text_url.setEditable(false);

		// エンコーディングをリストへ追加
		encoding_list = new JComboBox();
		encoding_list.addItem(ENCODING_SJIS);
		encoding_list.addItem(ENCODING_EUC);

		// ツールバーの定義
		JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
		toolbar.setLayout(new FlowLayout());
		toolbar.add(button_open);
		toolbar.add(text_url);
		toolbar.add(encoding_list);

		// HTML表示部へスクロールバーを追加
		JScrollPane scrollview = new JScrollPane(html_view);

		// ウインドウへコンポーネントを追加
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		panel.add(toolbar,BorderLayout.NORTH);
		panel.add(scrollview,BorderLayout.CENTER);
		setContentPane(panel);

		// ウインドウの表示
		setSize(800,600);
		setVisible(true);
	}

	public String getTextFromFile(File file)
	{
		String text = "";
		try
		{
			// 指定のエンコーディングで入力ストリームを構築
			String encoding = encoding_list.getSelectedItem().toString();
			FileInputStream input = new FileInputStream(file);
			BufferedReader reader = new BufferedReader(new InputStreamReader(input,encoding));

			// Stringオブジェクトに読み込む
			String buffer;
			while((buffer = reader.readLine()) != null)
			{
				// Metaタグを含む行を無視
				if(buffer.toLowerCase().indexOf("meta http-equiv") == -1)
				{
					text = text + buffer + line_separator;
				}
			}
		}
		catch(IOException e)
		{
			System.err.println(e);
		}

		return(text);
	}
}
Source is here. (ZIP Format,1707Byte,Shift-JIS)

コンパイル&実行
javac JEditorPaneDemo.java
java JEditorPaneDemo

説明
(概略)

今回のプログラムは、単純にローカルのHTMLを表示する機能のみを持ちます。
エンコーディングは、読み込み時にのみ変換出来、
ダイナミックに変換するようなことはしませんでしたが、
恐らく、java.io.StringReaderクラス辺りを使えば出来ると思います。

機能を最小限にしぼったのは、一応JEditorPaneクラスを説明するのに、
そこまでする必要は無いと考えたからです(いいわけ(^^;)
というわけで、このプログラム拡張などは、
皆さん自身で行ってくださいね。

実行イメージ

(サンプルプログラムの説明)

File current_path = new File("");
Fileオブジェクトを、空文字列で構築すると、
Javaプログラムを実行しているにディレクトリに設定されます。
System.getProperty("line.separator");
java.lang.System.getPropertyメソッドは、
プラットフォーム固有の値を取得するのに使います。
詳しくは、マニュアルを見てください。
final String ENCODING_SJIS = "Shift_JIS";
final String ENCODING_EUC = "EUC-JP";
それぞれの日本語エンコーディング名を表わします。
これらの文字列は、Netscape Communicator4.5を参考にしました。
(表示→文字コードセット)
html_view = new JEditorPane("text/html","<h1 align = \"center\">Html Viewer</h1>");
MIME Typeの設定は、text/htmlの他にも、
text/plainとtext/rtf(リッチテキストフォーマット)
があります。

また、あえてデフォルトのテキストを設定していますが、
この理由は、テキストが設定されていないJEditorPaneをクリックすると、
なぜか、ArrayIndexOutOfBoundsExceptionが発生するからです。
特に実害は無いんですけどね。
current_path.getAbsolutePath() + file_separator + e.getDescription()
ハイパーリンクがクリックされた時に、リンク先を表示する処理の一部ですが、
HyperlinkEvent.getDescriptionメソッドが返す値は、
aタグのhref属性に設定されている値なので、
例えば、
<a href = "zakki/index.html">雑記帳</a>
なら、"zakki/index.html"を返すことになります。

上記の例なら特に問題は無いのですが、
"href = zakki"や、href = "../zakki/index.html"
の場合、前者は、index.html(とは限らないが)を
暗黙で付け加える処理をしなければならない。
後者の場合、.や..を解釈して処理しなければならない。
など、結構面倒になってしまいますので、止めました。
JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
なんとなく、単なるPanelでは無く、JToolBarを実装してみました。
ToolBarの左の方にある、ぶつぶつ(?)の部分をドラッグすると、
メインウインドウから離脱して、フローティングするようになってます。
結構簡単に出来るので、やってみると面白いかも知れません。
Metaタグを含む行を無視
これは、JEditorPaneに、Metaタグを含むHTMLテキストをセットすると、
なぜか、何にも表示されないので、その行を排除するようにしています。
本来なら、その行を解釈して、エンコーディングや、
テキストファイルorHTMLファイルを自動的に判断する
などの処理が考えられますが、
今回は、簡単のために、そこまではしませんでした。