对于个人项目,我正在研究一种通过 JOptionPane 识别字符串的方法。现在我的目标是当我将它放入控制台然后关闭 JOptionPane 时也能识别它。为了实现这一目标,我试图实现一个应该并行工作的线程。因此,当 JOptionPane 打开时,控制台也应该能够获取命令并使用扫描仪对它们做出反应。然而它根本不起作用。线程没有与程序并行工作,但它似乎没有反应。
将控制台命令的扫描器放入线程或 JOptionPane 本身并不重要。另外,我首先调用的顺序(线程或扫描仪)根本不重要。结果始终相同,JOptionPane 从未显示,而是程序仅等待控制台的输入。只有在那之后 JOptionPane 才会显示,但那里的所有输入都会被忽略并被控制台中的前一个输入覆盖。
与此同时,我尝试了几种不同的尝试来解决这个问题,但都没有成功。我觉得我在这里错过了一些重要的东西,因为我没有人可以问,所以我希望你能帮助我。由于我没有想法,所以我需要比我更有经验的人的帮助。请帮我解决这个问题。
以下是我迄今为止尝试过的代码示例:
第一次尝试:
import javax.swing.JOptionPane;
public class NameConsole extends Thread {
public String answer = "";
public void run(){
answer = (String)JOptionPane.showInputDialog(
null,
"Please chose the reference. \n",
"choice of name",
JOptionPane.PLAIN_MESSAGE,
null,
null,
"");
}
}
public class SelectName {
public static String setManualname() {
try (Scanner sc = new Scanner(System.in)) {
NameConsole nameconsole = new NameConsole();
String name = "";
while (sc.nextLine().equals("")) {
nameconsole.run();
if (!nameconsole.answer.equals(""))
name = nameconsole.answer;
else if (sc.nextLine() != null)
name = sc.nextLine();
}
}
}
}
第二次尝试:
package engine.managers.collectors.identifier.nameconsole;
import javax.swing.JOptionPane;
public class NameConsole extends Thread {
public String answer = "";
public void run(){
answer = (String)JOptionPane.showInputDialog(
null,
"Please chose the reference. \n",
"choice of name",
JOptionPane.PLAIN_MESSAGE,
null,
null,
"");
}
}
public class SelectName {
public static String setManualname() {
try (Scanner sc = new Scanner(System.in)) {
String name = sc.nextLine();
NameConsole nameconsole = new NameConsole();
nameconsole.run();
while (name.equals("")) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!nameconsole.answer.equals(""))
name = nameconsole.answer;
else if (name != null)
break;
}
}
}
}
第三次尝试:
package engine.managers.collectors.identifier.nameconsole;
import java.util.Scanner;
public class NameConsole extends Thread {
Scanner sc = new Scanner(System.in);
public String answer = "";
public void run(){
answer = sc.nextLine();
}
}
public class SelectName {
public static String setManualname() {
String name = "";
String panelline = (String)JOptionPane.showInputDialog(
null,
"Please chose the reference. \n",
"choice of name",
JOptionPane.PLAIN_MESSAGE,
null,
null,
"");
NameConsole nameconsole = new NameConsole();
nameconsole.run();
while (name.equals("")) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (panelline != null)
name = panelline;
else if (!nameconsole.answer.equals(""))
name = nameconsole.answer;
}
}
}
这是一个我认为可以满足您需求的版本。它的工作原理是通过 CompletableFuture
在单独的线程中运行both 控制台提示符和 GUI 提示符。然后,主线程等待第一个完成并带有值的线程。
请注意,此实现依赖于在第一次响应后关闭公共线程池并退出程序,因为无法取消或中断阻塞的
Scanner.nextLine
调用。这可能不适合较大的程序。其他 Stack Overflow 答案(example)中介绍了此问题的解决方案,但它们比使用 Scanner 更复杂。
此实现的一个关键特征是它不依赖于线程之间共享的可变状态。
import javax.swing.*;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
public class SelectName {
private static String guiPrompt() {
return JOptionPane.showInputDialog(
null,
"Please chose the reference. \n",
"choice of name",
JOptionPane.PLAIN_MESSAGE);
}
private static String consolePrompt(Scanner sc) {
var answer = "";
while (answer.isEmpty()) {
System.out.print("Please chose the reference: ");
answer = sc.nextLine();
}
return answer;
}
public static String promptForName(Scanner sc) {
return (String) CompletableFuture.anyOf(
CompletableFuture.supplyAsync(SelectName::guiPrompt),
CompletableFuture.supplyAsync(() -> consolePrompt(sc))
).join();
}
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.println("\nUser entered: " + promptForName(sc));
ForkJoinPool.commonPool().shutdownNow();
System.exit(0);
}
}
}