如何在任何线程上从对话框中获取值?
How to get a value from a dialog when on any thread?
我想知道这是否是从对话框中获取 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
,因此一个对话框 "goes back" 可能会很棘手。
因此,首先,您的 GUI 代码需要检查您当前是否没有请求 pin,最好的方法是让一个 class 负责获取如有必要,请从用户那里获取密码,并且它应该处于静态状态。如果还应该检查此时是否没有显示其他对话框,如果是这样,它可能希望避免显示例如:
if(getCurrentForm() instanceof Dialog) {
// ... don't show yet
}
如果我正确理解你的问题,你有可能需要 pin 的后台线程。在那种情况下,可能会在没有 pin 的情况下捕获多个线程,并且需要来自 GUI 的线程。所以两个线程都需要暂停,但只有其中一个应该调用 callSeriallyAndWait
...这意味着当前的方法无论如何都低于标准。
通常我们会避免使用 callSeriallyAndWait
,因为它要慢得多(在 Swing 上也是如此)。我还会使用 InteractionDialog
或类似的东西,它比常规对话框的侵入性更小。但是,它不是模态的。但在这种情况下应该无关紧要。
您需要为后台线程开发自己的线程阻塞代码,它可以响应标准回调以释放所有等待的后台线程。然后,您可以使用任何您想要创建 GUI 的代码并使用任何侦听器,然后使用新 pin 更新 class 中的共享状态并调用 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();
}
}
我想知道这是否是从对话框中获取 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
,因此一个对话框 "goes back" 可能会很棘手。
因此,首先,您的 GUI 代码需要检查您当前是否没有请求 pin,最好的方法是让一个 class 负责获取如有必要,请从用户那里获取密码,并且它应该处于静态状态。如果还应该检查此时是否没有显示其他对话框,如果是这样,它可能希望避免显示例如:
if(getCurrentForm() instanceof Dialog) {
// ... don't show yet
}
如果我正确理解你的问题,你有可能需要 pin 的后台线程。在那种情况下,可能会在没有 pin 的情况下捕获多个线程,并且需要来自 GUI 的线程。所以两个线程都需要暂停,但只有其中一个应该调用 callSeriallyAndWait
...这意味着当前的方法无论如何都低于标准。
通常我们会避免使用 callSeriallyAndWait
,因为它要慢得多(在 Swing 上也是如此)。我还会使用 InteractionDialog
或类似的东西,它比常规对话框的侵入性更小。但是,它不是模态的。但在这种情况下应该无关紧要。
您需要为后台线程开发自己的线程阻塞代码,它可以响应标准回调以释放所有等待的后台线程。然后,您可以使用任何您想要创建 GUI 的代码并使用任何侦听器,然后使用新 pin 更新 class 中的共享状态并调用 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();
}
}