如何在任何线程上从对话框中获取值?



我想知道这是否是从对话框中获取PIN的正确方法?

public static <T> T getFromGui(Supplier<T> supplier) {
if (CN.isEdt()) return supplier.get();
final Object[] holder = new Object[1];
CN.callSeriallyAndWait(() -> holder[0] = supplier.get());
@SuppressWarnings("unchecked") final T result = (T) holder[0];
return result;
}
public static String askPin() {
if (!CN.isEdt()) return getFromGui(() -> askPin(bankzugang));
...
final boolean cont = Dialog.show(
"Your PIN", BoxLayout.encloseY(pin, label), ok, cancel) == ok;
return cont? pin.getText() : "";
}

它似乎有效(尝试过一次(,但我对callSeriallyAndWait有点困惑:它是SwingUtilities.invokeAndWait的类似物吗?有什么区别?

实际上,我需要几个对话框才能从每个线程(包括 EDT(工作。有没有比像上面那样为每个行添加"getFromGui"更好的方法?

是的,callSeriallyAndWait相当于SwingUtilities.invokeAndWait。没有逻辑上的区别。

这可以工作,但这里有一些问题......第一:

如果两个线程同时显示这样的对话框怎么办。第一个将处置以显示第二个对话框,该对话框可能会在无限循环中显示第一个对话框...即使您实际使用 EDT,也会发生这种情况,因为代码不是正常应用程序流的一部分。

与 Swing 不同,我们一次只有一个Form,因此对话框"返回",这可能会变得棘手。

因此,首先,您的 GUI 代码需要检查您当前是否没有请求引脚,最好的方法是让一个类负责在必要时从用户那里获取引脚,并且它应该具有静态状态。如果还应该检查此时是否没有显示其他对话框,如果是这样,它可能希望避免显示例如:

if(getCurrentForm() instanceof Dialog) {
// ... don't show yet
}

如果我正确理解您的问题,您的后台线程可能需要引脚。在这种情况下,可能会在没有引脚的情况下捕获多个线程,并且需要从 GUI 获取它。所以两个线程都需要挂起,但只有一个线程应该调用callSeriallyAndWait......这意味着目前的方法无论如何都低于标准。

通常我们避免callSeriallyAndWait因为它要慢得多(在 Swing 上也是如此(。我还会使用比常规对话框侵入性更小的InteractionDialog或类似内容。但是,它不是模态的。但在这种情况下,这应该无关紧要。

您需要为后台线程开发自己的线程阻塞代码,它可以对标准回调做出反应以释放所有等待的后台线程。然后,您只需使用要创建 GUI 的任何代码并使用任何侦听器,然后使用新引脚更新类中的共享状态,并调用notifyAll()来唤醒等待引脚的线程。例如

synchronized(LOCK) {
if(pin == null && !dialogIsShowing) {
dialogIsShowing = true;
callSerially(() -> promptForPin());
}
while(pin == null) {
LOCK.wait();
}
}

然后是 UI 逻辑:

private void onUserSubmittedPin(String pin) {
synchronized(LOCK) {
this.pin = pin;
dialogIsShowing = false;
LOCK.notifyAll();
}
}

最新更新