gpt4 book ai didi

java - 如何让 main 方法等待 GUI 上的输入而不使用 Listener 作为直接触发器?

转载 作者:行者123 更新时间:2023-12-01 15:14:52 26 4
gpt4 key购买 nike

我正在开发一个网络抓取工具,该工具应该使用抓取的数据执行各种操作。

因此,我需要各种不同的 GUI 才能有序工作,因此,我需要 main 方法在每个 GUI 完成其目的之前等待。

经过一段时间的搜索,我发现了以下 StackOverflow 问题,它们提供了一些有关如何解决问题的线索,但我无法实现,因为它们与我的情况有一些差异:

How to wait for input in a text field How to make main thread wait a different thread to finish

<小时/>

我知道我可以使用 GUI 组件(例如按钮)的监听器来触发代码,但我很难让主线程等待该监听器将其唤醒,而GUI 线程(如果有的话)的代码由主线程初始化...

<小时/>

这是一个简化的代码,用于演示程序应该如何工作:

public class Main {
/*
* Waiter is a simple GUI with just an "Start" button in it. Here in place of my actual GUIs.
*/
private static Waiter auth; //Represents my NTLM-authentication form.
private static Waiter status; //Represents a status-feedback GUI that will be displayed during processing.
private static Waiter operation; //Represents a GUI in with the user choses what to do with the gathered data.

public static void main(String[] args) throws InterruptedException {
auth = new Waiter();
auth.setVisible(true);
System.out.println("NTLM Authentication form. Should wait here until user has filled up the GUI and clicked \"Start\".");
System.out.println("Authenticates WebClient's NTLM using data inputed to the GUI...");
auth.dispose();
Thread srt = new Thread(status = new Waiter());
srt.start();
status.setVisible(true);
//Performs webscraping operations...
System.out.println("Prepares the webscraped data here...Things like downloading files and/or parsing text...");
System.out.println("Keeps the user aware of the progress using the \"status\" GUI.");
status.setVisible(false);
//Clears the status GUI.
operation = new Waiter();
operation.setVisible(true);
System.out.println("Operation selection form. Should wait here until user selects an option.");
System.out.println("Starts performing the operation(s)...");
operation.dispose();
status.setVisible(true);
System.out.println("Performs the operation(s), while giving status-feedback to the user.");
status.setVisible(false);
System.out.println("Displays a file-save dialog to save the results.");
System.out.println("And finally, displays a \"End of operations\" dialog before ending.");
}
}
<小时/>

更新1:我遇到的主要困难是实现这样的事情(这就是我想做的):

//Main method...code...
Thread srt = new Thread(status = new Waiter());
//Before "srt.start();"...
status.startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
main.continueExecution();
}
});
//Thread's run() being something like "status.setVisible(true); main.waitGUI();"
srt.start();
//continues here after the Listener is triggered...more code...

而不是这个(如果我理解正确的话,大多数其他人的解决方案是什么......)(这是我想要做的,如果可能的话):

//GUI before this one...
//code...
Thread srt = new Thread(status = new Waiter());
status.startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
/*
* Code that should come after this GUI.
*/
}
});
//Thread's run() being something like "status.setVisible(true);"
srt.start();
//"ends" here...(Initial code or GUI before this "status")

换句话说,我在实现 GUI 和监听器来触发主线程的“ sleep ”和“唤醒”操作时遇到了麻烦,而不是触发实际的处理代码。

<小时/>

更新2:

按照 @JB_Nizet 关于 SwingUtilities.invokeLater() 的提示,我仔细查看了 SwingUtilities docs ,在我发现 SwingUtilities.invokeAndWait() 方法如何工作之后,我想我已经找到了如何使用 SemaphoreinvokeAndWait().

我需要对多线程和/或 GUI 有更好了解的人来确认它是否是安全、有效的解决方案。 (然后我将编辑问题并清理它,如果得到确认,则以正确的“答案格式”发布)

无论如何,这是修改后的代码,它似乎对我有用:

public class Main_Test {

//Semaphore:
public static Semaphore semaphore;
//GUIs:
private static Waiter auth; //Represents my NTLM-authentication form.

public static void main(String[] args) {
try {
semaphore = new Semaphore(1);
// semaphore.acquire();
auth = new Waiter() {

@Override
public void run() {
try {
System.out.println(Main_Test.getThread() + this.getName() + " has been created and is now running.");
semaphore.acquire(); //Makes main pause.
this.setVisible(true);
} catch (InterruptedException ex) {
Logger.getLogger(Main_Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
auth.jButton1.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
System.out.println(getThread() + "NTLM has been hypothetically authenticated.");
semaphore.release(); //Makes main continue after GUI is done.
auth.dispose();
}
});
// semaphore.release();
SwingUtilities.invokeAndWait(auth);
semaphore.acquire(); //<- Where the main effectively gets paused until the permit is released.
/*
* GUI's run() will accquire the semaphore's permit.
* The invokeAndWait() garantees (?) it will happen before main's acquire().
* This causes the main to pause when trying to acquire the permit.
* It stays paused until the actionListener release() that permit.
*/
System.out.println(getThread() + "This message represents the processing, and should come only after the hypothetical NTLM authentication.");
} catch (InterruptedException ex) {
Logger.getLogger(Main_Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(Main_Test.class.getName()).log(Level.SEVERE, null, ex);
}
}

public static String getThread() {
return String.format("%-32s --- ", Thread.currentThread().toString());
}
}

最佳答案

我不确定我是否完全理解你想要做什么,但在我看来,你有一个消费者线程(主线程,等待来自事件调度线程的事件)和一个生产者线程(事件调度线程)。

实现这一点的典型方法是使用阻塞队列作为通信机制:

  • 创建阻塞队列
  • 创建 GUI 并将其传递给阻塞队列
  • 启动一个循环,从队列中获取数据。由于队列是阻塞的,因此主线程将被阻塞,直到队列中有东西
  • 让您的事件监听器在 EDT 中运行,将数据发布到阻塞队列

关于java - 如何让 main 方法等待 GUI 上的输入而不使用 Listener 作为直接触发器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11767788/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com