dポイントプレゼントキャンペーン実施中!

java(swing)で、登録ボタンを押すとファイルを読み込みDBに登録する処理です。
その処理で、登録ボタンを押すと、ダイアログを起動して、処理中とメッセージ表示したいのですが、データが多く、画面が固まった状態になり、メッセージが表示されないのです。何かいい方法ありますでしょうか?

*******************************************************************
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class topMain {
public static void main(String[] args) {

//メニュー画面を起動する
topMain frame = new topMain();
frame.topFrame();
}

private void topFrame() {

JFrame jf = new JFrame();

//フレームのサイズ設定
jf.setSize(1000, 600);
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

jf.getContentPane().setLayout(null);

JButton b1 = new JButton("登録ボタン");

b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

//ダイアログボックスを開く
    //ダイアログボックスは起動するが、
//メッセージが表示されない、
//おそらく大きいデータを読むとき画面が固まるため
//重いファイルを読み込む
//DB登録処理
//ダイアログを閉じる
}
});
jf.getContentPane().add(b1);

b1.setBounds(40, 400, 240, 100);

jf.setVisible(true);
}
}
*******************************************************************

A 回答 (2件)

actionPerformedメソッドはswingでの表示や入力などを処理している唯一のスレッドであるイベントディスパッチスレッド上で呼ばれ実行される。


したがってactionPerformed内で時間の掛かる処理をすることは表示処理などを行う機会が失われるのでこれを行ってはならない。
替わりにactionPerformed内では時間の掛かる処理を開始する機会だけを与えて、その処理自体は別スレッドで行うようにする。
例えばactionPerformed内を以下のような感じに。

final JDialog d = new JDialog();
d.add(new JLabel("ファイル読み込み&DB登録中"));
d.pack();
d.setVisible(true);
new Thread(new Runnable() {
public void run() {
...時間の掛かる処理をここに記述...
SwingUtilities.invokeLater(new Runnable() {
public void run() {
d.setVisible(false);
d.dispose();
}
});
}
}).start();

「時間の掛かる処理を行った後、ダイアログを閉じる」という処理をrunメソッドに書き、それを別スレッドで実行する。

上の例は非モーダルダイアログの場合で、モーダルダイアログの場合はsetVisible(true)した時点でダイアログが閉じられるまで処理が先に進まなくなるので、

final JDialog d = new JDialog((JFrame)null, true);
final JProgressBar pb = new JProgressBar();
pb.setIndeterminate(true);
pb.setStringPainted(true);
d.add(pb);
d.pack();
d.addWindowListener(new WindowAdapter() {
@Override public void windowOpened(WindowEvent e) {
new Thread(new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pb.setString("ファイルから読み込み中");
}
});
...時間の掛かる読み込み処理をここに記述...
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pb.setString("DBへ登録中");
}
});
...時間の掛かる登録処理をここに記述...
SwingUtilities.invokeLater(new Runnable() {
public void run() {
d.setVisible(false);
d.dispose();
}
});
}
}).start();
}
});
d.setVisible(true);

のようにダイアログを開いた時点でスレッドを開始するようにWindowListenerを前もってダイアログに登録しておく方法が考えられる。

もし進捗状況まで示したいならJProgressBarやProgressMonitor、ProgressMonitorInputStreamなどが結構便利だと思う。
また、別スレッドでの実行を記述する場合に1.6以降ならSwingWorkerの使用を検討してみてもいいかも。
    • good
    • 0

意味がいまいち分からないんだけど



DBから読み込むデータが多くて
VMへの負荷が高くて
ダイアログにメッセージを表示する余裕がない
ってこと?

だとしたら、読み込みを開始する前に
ダイアログを表示すれば良いんじゃない?

この回答への補足

回答ありがとうございます。

以下のソースを実行したとき、LABEL「実行中」の値を表示したいのですが、ダイアログが固まった状態になり、値が表示されないのです。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class topMain {
public static void main(String[] args) {
//メニュー画面を起動する
topMain frame = new topMain();
frame.topFrame();
}
private void topFrame() {
JFrame jf = new JFrame();
//フレームのサイズ設定
jf.setSize(1000, 600);
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jf.getContentPane().setLayout(null);
JButton b1 = new JButton("登録ボタン");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

//ダイアログボックスを開く
JDialog jd =new JDialog();
jd.setTitle("ddddddddd");
jd.getContentPane().add(new JLabel("実行中"),BorderLayout.CENTER);
//jd.getContentPane().setLayout(null);
jd.setBounds(10, 10, 50, 20);
jd.setSize(100,100);
jd.setVisible(true);

//ファイルを読み込む
long i=0;
while(true){

if(i==800000000){
break;
}
i++;

//ダイアログを閉じる
jd.dispose();
System.out.println("END");
}
});
jf.getContentPane().add(b1);
b1.setBounds(40, 400, 240, 100);
jf.setVisible(true);

}
}

補足日時:2010/08/13 14:22
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!