07

22

[Java] ThreadからGUIに画像を表示する / 外部のThreadから指定されたタイミングでJava Swing JFrameに画像を表示する

2012.07.22(21:50)

GUIシステムは自分でイベントドリブンのしくみを持ち、自分がわかっているマウス操作やキー入力に対する再描画のしくみを実現することができる。しかし実行中はイベントドリブンを全力で実行しているため、自分が決めた好きなタイミングで再描画できるようにするには一工夫が必要だ。

外部のThreadから、自分が決めた好きなタイミングでJava Swing JFrameに画像を表示するサンプルを作ってみた。

まずGUIシステム側。
import java.awt.*;
import javax.swing.*;

class ImageFrame extends JFrame
{
    Image img;
    final int WIDTH = 600;
    final int HEIGHT = 400;
    
    public ImageFrame()
    {
        super("ImageFrame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(WIDTH, HEIGHT);
        setVisible(true);
        //img = getToolkit().getImage("java.jpg");
    }

    public void drawImage(String imageFile)
    {
        System.out.println("drawImage " + imageFile);
        img = getToolkit().getImage(imageFile);
        repaint();
    }
    
    public static void main(String args[])
    {
        ImageFrame frame = new ImageFrame();
        frame.drawImage("java.jpg");
    }

    public void paint(Graphics g)
    {
        super.paint(g);
        if (img == null) {
            g.drawString("JFrame Ready", WIDTH/2-100, HEIGHT/2);
        } else {
            g.drawImage(img, (WIDTH - img.getWidth(this))/2, 
                             (HEIGHT - img.getHeight(this))/2, this);
        }
    }
}

GUIシステム側では任意のタイミングで画像を表示させるしくみを組み込むことはできない。そのため、まず外部から呼び出せる drawImageメソッドを用意し、そこからGUIシステムに対して repaintを呼び出して、再描画する必要があることを知らせる。GUIシステムはイベントループの中で再描画の必要があることに気づいて paintを呼び出して再描画を実現する。

外部にThreadを用意し、そちらで自分でタイミングを作って drawImageを呼び出して、画像描画要求をおこなわせる。

画像描画要求をおこなうThread側
class ImageServer extends Thread {
    ImageFrame m_frame;
    public ImageServer() {
        m_frame = new ImageFrame();
    }

    public void run() {
        try {
            sleep(2000);
            for(int i=0;i<5;i++) {
                sleep(1000);
                m_frame.drawImage("java.jpg");
                sleep(1000);
                m_frame.drawImage("java_black.jpg");
            }
        } catch(InterruptedException e) {
        }
    }

    public static void main(String args[]) {
        ImageServer server = new ImageServer();
        server.start();

        System.out.println("close ImageFrame");
        try {
            server.join();
        } catch(InterruptedException e) {
        }
    }
}

このように2つに分けることで、自分の好きなタイミングで画像を表示できるようになる。

同様のことをRubyでやってみた。

[Ruby] ThreadからGUIに画像を表示する / 外部のThreadから指定されたタイミングでRuby/Tkに画像を表示する
http://saltheads.blog134.fc2.com/blog-entry-75.html

プロフィール

島敏博

Shima Toshihiro 島敏博
信州アルプスハイランド在住。HaskellとElixirが好き。組み込みソフトウェアアーキテクト、C++プログラマ、山歩き、美術館巡り、和食食べ歩き、日本赤十字社救急法指導員、インデックス投資、クラシック音楽、SESSAME会員、状態マシン設計、モデル駆動開発、ソフトウェアプロダクトライン、Rubyist、実践ビジネス英語

■ ツイッター
http://twitter.com/saltheads
■ Facebook
http://www.facebook.com/saltheads
■ Qiita
http://qiita.com/saltheads

印刷する場合は、ブラウザの印刷メニューではなく、このページの上から3cmくらいの青いところにある、「印刷」を押してみてください。少しうまく印刷できます。まだ完全ではないのですが、これで勘弁してください。


カテゴリ
最新記事
月別アーカイブ
最新コメント
検索フォーム
リンク
sessame
RSSリンクの表示