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
イベントディスパッチスレッドとは?
TechTargetジャパン
キャリアアップ
**先週の人気講座ランキング**
〜 Android編 〜