私は仕上げに並列タスクを待っている前に、すなわちJProgressBar
、Swingコンポーネントを操作する理由を理解しようと悩みを抱えています。スウィングがコンポーネントをスイングするのを遅らせるのを待っているのはなぜですか?
次の例では、setIndeterminate(true)
の呼び出しが待機する前に発生していても、スレッドがCallable
の結果の待機を終了した後にprogressbarがその不確定モードを有効にします。誰かがなぜこれが起こるのか説明できますか?
private void thisDoesntWork(JProgressBar p){
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> jobResult = executor.submit(() -> aLengthyJob());
// This happens only after the button finishes waiting. (future.get())
// I want to know why. Shouldn't this line happen before the thread blocks?
p.setIndeterminate(true);
try {
System.out.println(jobResult.get());
} catch (InterruptedException | ExecutionException ex) {}
}
public void createAndShowGUI(){
JFrame frame = new JFrame("This progress bar wont work");
JPanel panel = new JPanel();
JButton button = new JButton("Start");
JProgressBar progressBar = new JProgressBar();
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
// Problem happens withing this button's action
button.addActionListener((e)->{
thisDoesntWork(progressBar);
});
panel.add(button);
panel.add(progressBar);
frame.add(panel);
frame.setVisible(true);
}
private String aLengthyJob(){
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {}
return "Done";
}
public static void main(String[] args) {
new Test().createAndShowGUI();
}
待機中は別のスレッドで発生した場合、予想通り、それは動作します。
// Waiting in a third thread works fine
private void thisWorks(JButton b, JProgressBar p) {
p.setIndeterminate(true);
b.setEnabled(false);
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> jobResult;
jobResult = executor.submit(() -> aLengthyJob());
executor.execute(() -> {
try {
System.out.println(jobResult.get());
p.setIndeterminate(false);
b.setEnabled(true);
} catch (InterruptedException | ExecutionException ex) {}
});
}
輸入:それをブロックEDT内の他のスレッドの終了を
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
通常の答えは、あなたは何とかイベントのディスパッチャスレッドを混乱させました。 https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html – GhostCat
setIndeterminate' 'の呼び出しは' jobResult.get() 'の前に起こるが、プログレスバーは、実際にその外観を(更新することはできませんこれは現在のアクションイベントが返るまで再ペイントが必要です)。 'thisDoesn'tWork(へのあなたの呼び出しを)'、 'ActionListener'である:あなたが他の – Radiodef
@GhostCat、 'ActionListener'は常にイベントディスパッチスレッド(EDT)によって呼び出されます。 ActionListenerが呼び出されたときはいつでも、あなたのプログラムは、画面上で何かを描くことができない、とのコールが戻るまで、すべてのユーザー入力に応答することができません。 –