SwingでJavaに強くなる(6)
Swingのスレッド処理を理解する


シンプレクス・テクノロジー
島浩文
2006/9/23



 第5回では、ToDoリストの表示とToDoの追加を実装しました。第6回ではさらなる機能の実装と前回触れていない点について解説を行います。

今回作成するGUIアプリケーションの仕様

 今回は第5回で作成したアプリケーションに対して以下の機能を実装します。

  • 一覧のToDoを編集する
  • 一覧のToDoを削除する
図1 ToDoリストのイメージ

ToDoリストの実装

■プロジェクトの作成

 今回は「ToDoList2」という名前のプロジェクトを作成します(第1回の“プロジェクトの作成”を参考にしてください)。

■SwingAppMainクラスの作成

 アプリケーションの起動および土台となるフレームの生成を担当するクラス「SwingAppMain」を作成します。

package swing.sample;

import java.awt.BorderLayout;
import java.awt.Container;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class SwingAppMain {

        /**
         * アプリケーションの起動
         */
        public static void main(String[] args) {
                System.out.println("main : "
                        + SwingUtilities.isEventDispatchThread());

                SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                                createAndShowTodoList();
                        }
                });
        }

        /**
         * ToDoリストの生成と表示を行います。
         */
        private static void createAndShowTodoList() {

                System.out.println("createAndShowTodoList :"
                                + SwingUtilities.
                                isEventDispatchThread());

                JFrame mainFrame = new JFrame("ToDoリスト");
                mainFrame.setDefaultCloseOperation
                (JFrame.EXIT_ON_CLOSE);

                Container contentPane =
                mainFrame.getContentPane();

                // ToDoリストを生成
                JComponent newContentPane = new ToDoListPane();
                contentPane.add(newContentPane,
                BorderLayout.CENTER);

                // Windowサイズを調整
                mainFrame.pack();
                // 表示
                mainFrame.setVisible(true);
          }
}

■TodoListPaneクラスの生成

 次にToDoListPaneクラスを作成します。このクラスは、ToDoリストのすべての機能を提供するクラスです。

package swing.sample;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * ToDoリスト
 */
public class ToDoListPane extends JPanel {

        private JList toDoList;

        private DefaultListModel toDoListModel;

        private JTextField toDoInputField;

        private JButton addButton;

        private JButton modifyButton;

        private JButton removeButton;

public ToDoListPane() {
            super(new BorderLayout());

            // 一覧を生成
            toDoListModel = new DefaultListModel();
            toDoList = new JList(toDoListModel);
            JScrollPane listScrollPane = new JScrollPane(toDoList);
            // TODOリストにリスナを設定
            toDoList.addListSelectionListener
            (new ToDoListSelectionHandler());

            // ToDo追加用テキストフィールドの生成
            toDoInputField = new JTextField();


            // 各ボタンの生成
            JPanel buttonPanel = new JPanel();
            addButton = new JButton("追加");
            modifyButton = new JButton("編集");
            removeButton = new JButton("削除");

            // ボタンにリスナを設定
            addButton.addActionListener
            (new AddActionHandler());
            modifyButton.addActionListener
            (new ModifyActionHandler());
            removeButton.addActionListener
            (new RemoveActionHandler());

            buttonPanel.add(addButton);
            buttonPanel.add(modifyButton);
            buttonPanel.add(removeButton);

            add(listScrollPane, BorderLayout.NORTH);
            add(toDoInputField, BorderLayout.CENTER);
            add(buttonPanel, BorderLayout.SOUTH);
        }

        /**
         * TODOリスト選択アクションのハンドラ
         */
        private class ToDoListSelectionHandler
        implements ListSelectionListener {
                public void valueChanged(ListSelectionEvent arg0) {

                        // TODOリストのどの行も選択されて
                        いない場合や、
                        // 複数行が選択されている場合は、
                        // 何もしません
                        if (toDoList.getSelectedIndices().
                        length!=1){
                                    return;
                        }

                        toDoInputField.setText((String)toDoList.
                        getSelectedValue());
                }
        }

        /**
         * 追加ボタンアクションのハンドラ
         */
        private class AddActionHandler implements ActionListener {

                public void actionPerformed(ActionEvent e) {
                        // テキストフィールドの内容を
                         リストモデルに追加
                        toDoListModel.addElement
                        (toDoInputField.getText());
                }
        }

        /**
         * 編集ボタンアクションのハンドラ
         */
        private class ModifyActionHandler
        implements ActionListener {

                public void actionPerformed(ActionEvent e) {
                        // テキストフィールドの内容で
                        リストモデルを編集

                        // TODOリストのどの行も
                        選択されていない場合や、
                        // 複数行が選択されている場合は、
                        // 何もしません
                        if (toDoList.getSelectedIndices().
                        length != 1) {
                                return;
                        }

                        toDoListModel.set(toDoList.
                        getSelectedIndex(),
                        toDoInputField.getText());
                }
        }

        /**
         * 削除ボタンアクションのハンドラ
         */
        private class RemoveActionHandler
        implements ActionListener {

                public void actionPerformed(ActionEvent e) {
                        // テキストフィールドの内容を
                        リストモデルに追加

                        // TODOリストのどの行も
                        選択されていない場合や、
                        // 複数行が選択されている場合は、
                        // 何もしません
                        if (toDoList.getSelectedIndices().
                        length != 1) {
                                return;
                        }

                        setButtonsEnabled(false);
                        Thread removeThread = new
                        RemoveThread(toDoList.getSelectedIndex());
                        removeThread.start();
                }

        }

        /**
         * ボタンの状態を更新します
         */
        private void setButtonsEnabled(boolean enabled) {

                addButton.setEnabled(enabled);
                modifyButton.setEnabled(enabled);
                removeButton.setEnabled(enabled);
        }

        /**
         * 削除処理を行うクラス
         */
        class RemoveThread extends Thread {
                int index;
                RemoveThread(int index) {
                        this.index = index;
                }

                public void run() {
                        // 時間のかかる処理を実行
                        doLongTask();

                        // イベントディスパッチスレッドで
                        ボタンを変更
                        SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                        toDoListModel.
                                        remove(index);
                                        setButtonsEnabled(true);
                                }
                        });
                }
        }

        /**
         * 時間のかかる処理
         */
        private void doLongTask() {
                try {
                        Thread.sleep(10000);
                } catch (InterruptedException ex) {

                }
        }

■アプリケーションの実行

 「SwingAppMain」クラスを実行し、ToDoを追加してみます(図2では「20:00退社」の追加を試みようとしている)。

図2 アプリケーションの実行結果

 なお、今回は以下のような機能を実装しました。

(1)[編集]ボタンをクリックすると、一覧の選択されている1行の文字列がテキストフィールドに表示されている文字列に変更される

図3 図2の状態から、(1)を実行した結果

(2)[削除]ボタンをクリックすると、一覧の選択されている1行が削除される

図4 図2の状態から(2)を実行した結果


  1/2

 INDEX

Swingのスレッド処理を理解する
Page1
今回作成するGUIアプリケーションの仕様
  Page2
イベントディスパッチスレッドとは?


Java Solution全記事一覧

TechTargetジャパン

Java Solution フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH