Swingで重い処理はどう書く?
こんな感じかな?
package verticalviewer.action; import java.awt.*; import java.awt.event.ActionEvent; import java.lang.reflect.InvocationTargetException; import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultMutableTreeNode; import org.sourceforge.swingx.SxProgressDialog; import verticalviewer.VerticalViewer; import verticalviewer.model.VvDatabase; import verticalviewer.model.DbException; import verticalviewer.view.*; public class DatabaseConnectAction extends AbstractAction { VerticalViewer tools; SxProgressDialog progressDialog; public DatabaseConnectAction(VerticalViewer tools) { super("接続(C)"); putValue(MNEMONIC_KEY, new Integer('C')); putValue(SHORT_DESCRIPTION, "データベースに接続"); putValue(LONG_DESCRIPTION, "データベースに接続"); this.tools = tools; } public void actionPerformed(ActionEvent ev) { // 選択されているツリーを取得 DbTreeFrame treeFrame = tools.getTreeFrame(); DbTreeView tree = tools.getTreeFrame().getTree(); VvDatabase db = tree.getSelectedDatabase(false); if (db == null) return; // DBが選択されていない。 // すでに接続されているか? if (db.getConnection() != null) return; // デフォルトのユーザ String user = db.user; String pass = db.password; // 接続時にユーザ名とパスワードを問い合わせるか? if (db.isShowLoginDialog) { ConnectDialog dialog = new ConnectDialog(); dialog.setDatabase(db); int ret = JOptionPane.showConfirmDialog(treeFrame, dialog, "データベースへの接続", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (ret != JOptionPane.OK_OPTION) return; // キャンセル user = dialog.getUser(); pass = dialog.getPass(); } // 接続を別スレッドで行う。 new ConnectThread(db, user, pass).start(); } class ConnectThread extends Thread { VvDatabase db; String user; String pass; ConnectThread(VvDatabase db, String user, String pass) { this.db = db; this.user = user; this.pass = pass; } public void run() { final DbTreeFrame treeFrame = tools.getTreeFrame(); setMouseCursor(treeFrame, new Cursor(Cursor.WAIT_CURSOR)); try { // ユーザから他の操作が行えないように、ダイアログをモーダルで開く。 // このダイアログをイベントディスパッチスレッドから呼ぶことはできない。 // なぜなら、イベントディスパッチスレッドでモーダルで開くと、 // そのダイアログを閉じない限り、次の処理に行かない。 SwingUtilities.invokeLater(new Runnable() { public void run() { progressDialog = new SxProgressDialog(treeFrame, "データベースへの接続", null); progressDialog.setProgress(10, "接続中..."); progressDialog.setVisible(true); } }); // 接続 db.connect(user, pass); // ←これが重い処理☆ // 後処理 SwingUtilities.invokeLater(new Runnable() { public void run() { try { progressDialog.dispose(); DbTreeView tree = treeFrame.getTree(); DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent(); tree.接続したので枝を作る(node, db); treeFrame.updateMainFrame(); } catch(DbException e) { tools.showMessage(treeFrame, "データベースの接続に失敗しました", e, VerticalViewer.ERROR_MESSAGE); } } }); } catch (DbException e) { tools.invokeShowMessage(treeFrame, "データベースの接続に失敗しました", e, VerticalViewer.ERROR_MESSAGE); // TODO 自動生成された catch ブロック e.printStackTrace(); } setMouseCursor(treeFrame, Cursor.getDefaultCursor()); } } /** * マウスカーソルを設定します。 * 別スレッドからこのメソッドを呼ぶことを想定しています。 * Swingのイベントディスパッチスレッドでなくても構いません。 * @param comp * @param cursor */ private void setMouseCursor(final Component comp, final Cursor cursor) { try { SwingUtilities.invokeAndWait( new Runnable() { public void run() { comp.setCursor(cursor); } }); } catch (InterruptedException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }