はじめに
Webの世界で「Java」と言うと、サーバサイドでの利用がまず思い浮かびます。が、この他に、クライアントサイドで使われる「アプレット」も重要な役割を果たします。今回は、このアプレットと、サーバサイドのプログラム(サーブレット)の間でイメージを利用するための基本について説明しましょう。
対象読者
- Javaの基本およびJavaによるWeb開発の基礎(JSP/サーブレット程度)をマスターしている人。
- グラフィック関連のプログラミング経験があまりない人。
- Javaのグラフィック処理を学び直したい人。
アプレットでイメージを扱う
アプレットと言うと「Javaプラグインが必要になる」「クライアント側でしか動かない」「ローカルボリュームにアクセスできないなど制約が大きい」「起動に時間がかかる」「動作が遅い」……などなど、正直いってどうもあまり評判がいいものとはいえないところがあります。が、ハードウェアの進歩により、起動時間や動作速度などはほぼ実用レベルで動くようになっており、もう少し見直されてもよいのではないでしょうか。
アプレットは、「Webサイトで、Javaを使ってGUIを作成し提供する」という場合、非常に重要です。Swingを使えばHTMLなどよりも高度なGUIを提供できますし、サーバと連動してインタラクティブな動作を行わせることもできます。最近ではAjaxのような形態でダイナミックなページを作成する手法も出てきましたが、アプレットも決して廃れることはないように思えます。
アプレットの基本については、ここでは省略します。まずは、アプレットでイメージを利用する際の基本的な扱い方から簡単に説明しておくことにしましょう。ここでは、サンプルとして「マウスでドラッグし描画できるアプレット」を用意し、そのイメージをサーバに送信して保存したり、またサーバからイメージを送ってもらって表示したりできるようにしてみます。
まずは、アプレットからです。ここでは、ImageMaker
というクラスとしてアプレットを用意することにします。またイメージの描画用にImagePanel
というパネルクラスを作成し利用することにしましょう。
package jp.tuyano.codezine; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.net.*; import javax.swing.*; import javax.imageio.*; import javax.imageio.stream.*; public class ImageMaker extends JApplet implements ActionListener { private static final long serialVersionUID = 1L; private ImagePanel panel; private JLabel msg; private JButton b1,b2; private String servpath; public void init(){ servpath = this.getCodeBase() + "app2serv"; this.setLayout(new BorderLayout()); msg = new JLabel("ドラッグして描画できます。"); this.add(msg); panel = new ImagePanel(); this.add(panel,BorderLayout.CENTER); JPanel rowpanel = new JPanel(); b1 = new JButton("SAVE"); b1.addActionListener(this); rowpanel.add(b1); b2 = new JButton("LOAD"); b2.addActionListener(this); rowpanel.add(b2); this.add(rowpanel,BorderLayout.SOUTH); } public void actionPerformed(ActionEvent ev){ if (ev.getSource() == b1) saveImage(ev); if (ev.getSource() == b2) loadImage(ev); } // イメージをサーバに送って保存する private void saveImage(ActionEvent ev){} // イメージをサーバから受け取り表示する private void loadImage(ActionEvent ev){} } } class ImagePanel extends JPanel implements MouseMotionListener { private static final long serialVersionUID = 1L; private BufferedImage img; private Graphics2D g; public ImagePanel(){ this.addMouseMotionListener(this); } public void mouseDragged(MouseEvent ev) { g.setPaint(Color.BLACK); g.fillOval(ev.getX()-5,ev.getY()-5,10,10); repaint(); } public void mouseMoved(MouseEvent ev) {} public void paint(Graphics g2){ if (img == null){ img = new BufferedImage(this.getWidth(), this.getHeight(),BufferedImage.TYPE_INT_RGB); g = img.createGraphics(); g.setPaint(Color.WHITE); g.fillRect(0,0,this.getWidth(),this.getHeight()); } g2.drawImage(img,0,0,this); } public BufferedImage getDrawImage(){ return img; } public void setDrawImage(BufferedImage im){ g.drawImage(im,0,0,this.getWidth(),this.getHeight(), 0,0,im.getWidth(),im.getHeight(),this); repaint(); } }
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-31j"> <title>Applet2Servlet</title> </head> <body> ※アプレット=サーブレット間通信のサンプル<br> <applet code="jp.tuyano.codezine.ImageMaker.class" width="300" height="250"> </applet> </body> </html>
基本的なAWT/Swingの使い方がわかっていれば、そう説明することはないでしょう。アプレットは、基本的にjava.applet.Applet
クラスか、javax.swing.JApplet
クラスを継承して作成します。
ここではJButtonを2つ用意し、それぞれsaveImage
/loadImage
というメソッドを呼び出すようにしてあります。これらのメソッドに、イメージをサーバに送信したり、サーバから受信する処理を用意すればいいわけです。なお、ここではJDK 5以降での利用を前提に考えてあるため、コンポーネントの組み込みはthis.getContentPane().add
ではなく、単にthis.add
で行っています。
実際にイメージを扱っているImagePanel
クラスでは、BufferedImage
とGraphics2D
インスタンスをprivateフィールドとして用意し、これに描画を行うようにしています。マウスでドラッグをしたら、ここに描画を行ってからBufferedImage
を丸ごとパネルに描画するわけです。
こうしたイメージを表示するタイプのアプレットでは、このように「表示用のイメージをフィールドとして持たせ、必要に応じてこれを書き換えて画面に描画する」という方式をとります。一般に「オフスクリーンバッファリング」あるいは「ダブルバッファリング」と呼ばれる方式です。Swingの場合はそれほど重要ではありませんが、AWTの場合には画面のちらつきを抑えるためにもダブルバッファリングは必須でしょう。