这是在单元测试的背景下(发生时)。
在测试结束时,无论结果如何,我都希望代码检查JFileChooser
对话框的存在(可见性)......如果可见,则将其关闭。
当然,有不同的方法可以解除对话,但为了模仿人类行为(并举一个我在这里关心的问题的例子),我选择使用java.awt.Robot
. 后者的方法应该在非 EDT 线程中运行。
事实上,我已经扩展了 Robot 以包含一个名为 的便捷方法type_input
,所以
robot.type_input( KeyEvent.VK_F4, KeyEvent.VK_ALT )
先按 Alt,然后 F4,然后释放 F4,然后 Alt:就像人类关闭窗口/对话框一样。
我提交Runnable
使用invokeAndWait
,因为我不希望代码在此对话框被关闭之前运行到下一个测试。我必须在 EDT 中测试可见性和焦点。但正如我所说,Robot 方法必须在非 EDT 中运行。
get()
在 EDT 中这样进行是否有任何潜在问题?它是否可能导致 GUI 无响应?问题是,我听说该框架能够在某些条件下“启动一个新的 EDT 泵”。我不得不承认,这是我觉得自己最不了解的与 EDT 相关的问题之一……
import java.awt.EventQueue;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
class MainFrame extends JFrame {
JFileChooser update_target_file_chooser;
JDialog file_chooser_dlg;
// ... rest of class
}
public class ThreadWithinThread {
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
final ExecutorService thread_pool_exec_serv = Executors.newFixedThreadPool( 5 );
class DismissDlg implements Runnable {
MainFrame main_frame;
Robot robot;
@Override
public void run() {
boolean focus_on_dlg = main_frame.file_chooser_dlg.hasFocus();
if( main_frame.file_chooser_dlg.isVisible() ){
if( ! focus_on_dlg ){
main_frame.file_chooser_dlg.requestFocus();
}
class AltF4 implements Callable<Void>{
public Void call(){
return robot.type_input( KeyEvent.VK_F4, KeyEvent.VK_ALT );
}
}
Future<Void> future_result = thread_pool_exec_serv.submit( new AltF4() );
try {
// this is the line I'm worried about
future_result.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
EventQueue.invokeAndWait( new DismissDlg() );
}
}
之后
正如我在回复中所说,这不是针对手头案例的一个特别实用的解决方案:我真的想了解另一个 EDT“事件泵”是否以及何时启动并Future.get()
阻塞 EDT。正如我所说,我发现这整个方面很难理解。我使用JOptionPane
's 的静态方法(必须在 EDT 中运行,请参阅 SO ad 上的帖子)向我证明这些方法(确实会阻止 EDT!)实际上似乎并没有阻止 GUI 运行(注意不要与这些JOptionPane
s 或它们JDialog
的 s 是模态的还是非模态的混淆)。
我的理解是,这是因为“框架”随后启动了另一个“事件泵”。那么它可以在这里这样做吗?