在 gui 事件之后阻塞主线程
Blocking main-thread after gui-event
我一直在制作一个程序,该程序从文件中读取,识别文件中的常见 "posts",并对这些内容进行总结。我的问题是允许用户指定 post 的名称和搜索词的 GUI 事件不会像我希望的那样中断程序的运行。
我可以让它停止,但是这样GUI就不能正确显示了。我已经尝试了一些解决方案,这些解决方案将在post.
的底部指定
编辑:删除了代码转储并添加了类似于 SSCCE 的内容:
class SSCCE{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new Gui();
}
});
}
}
class Gui implements ActionListener{
boolean runn=true;
JFrame wind2;
JTextField nameF, searchtermF;
JButton done;
Gui(){
runEx();
}
public void runEx(){
int i =0;
while(runn){
if(i==10) break;
System.out.println("Open window and record information given! One at the time!!!");
System.out.println(" ");
giveName("test");
i++;
}
}
public void giveName(String s){
JLabel nameL = new JLabel("Give this post a name:");
JLabel searchL = new JLabel("What do you want the searchterm to be?");
wind2 = new JFrame("EazyMoney");
wind2.setLayout(new BorderLayout());
JPanel all = new JPanel();
all.setLayout(new GridLayout(2,2));
searchtermF = new JTextField(30);
nameF=new JTextField(30);
all.add(nameL);
all.add(nameF);
all.add(searchL);
all.add(searchtermF);
done = new JButton("Press when you have filled in the information!");
done.addActionListener(this);
String prn = "The post in question: " + s;
JLabel header = new JLabel(prn);
wind2.add(header, BorderLayout.NORTH);
all.setVisible(true);
wind2.add(all, BorderLayout.CENTER);
wind2.add(done, BorderLayout.SOUTH);
wind2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wind2.pack();
wind2.setLocationRelativeTo(null);
wind2.validate();
wind2.setVisible(true);
}
public void actionPerformed(ActionEvent e){
System.out.println("Action recorded, new window can now be shown. All information stored.");
System.out.println(" ");
}
}
我尝试过的解决方案是:
- 一个简单的块,执行
while(true){}
并在 g.giveName()
的第一个实例被调用后将变量设置为 true。我使用 ActionListener
调用一个方法,然后在提供必要的输入时再次将变量更改为 false。这导致出现一个灰色框,里面什么也没有。
- 制作一个与上面的方块相同的循环屏障。使用单独的线程调用
g.giveName()
,然后从动作侦听器调用 await()
。结果同上。
- 使
readFile
由单独的线程运行并在 g.giveName()
函数上调用 invokeAndWait()
。给出 cannot call invokeAndWait() from the EDT-thread
,即使它是从新线程运行的。
我无法给出上面实例中使用的代码示例,因为我尝试了很多不同的解决方案并且没有了。请考虑到它可能实施错误,因此可能是我问题的有效答案,即使我似乎无法让它工作!
最后说明:所有工作都可以在这里找到,如果你想测试代码:
https://github.com/Robiq/EazyMoneyWork
如果您需要在同一线程上执行其他操作,避免阻塞 EDT 的方法是临时创建一个新的事件队列。这是一些示例代码。在这种情况下,它会阻止当前线程等待其他事件发出信号,但您可以将其替换为需要的任何长 运行 进程。
首先检查您是否 运行 在美国东部时间:SwingUtilities.isEventDispatchThread
。那么如果你是:
EventQueue tempEventQueue = new EventQueue();
Toolkit.getDefaultToolkit().getSystemEventQueue().push(tempEventQueue);
try {
wait();
} catch (InterruptedException ex) {
// stop waiting on interrupt
} finally {
tempEventQueue.pop();
}
模态对话框在 Swing 中的工作方式与此类似。但总的来说,这不是好的做法。更好的方法是了解要侦听哪些事件以执行特定操作。在您的情况下,用户事件不应该 'stop' 您的程序 - 它应该禁用不适当的组件,直到用户响应然后重新启用它们。
我一直在制作一个程序,该程序从文件中读取,识别文件中的常见 "posts",并对这些内容进行总结。我的问题是允许用户指定 post 的名称和搜索词的 GUI 事件不会像我希望的那样中断程序的运行。
我可以让它停止,但是这样GUI就不能正确显示了。我已经尝试了一些解决方案,这些解决方案将在post.
的底部指定编辑:删除了代码转储并添加了类似于 SSCCE 的内容:
class SSCCE{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new Gui();
}
});
}
}
class Gui implements ActionListener{
boolean runn=true;
JFrame wind2;
JTextField nameF, searchtermF;
JButton done;
Gui(){
runEx();
}
public void runEx(){
int i =0;
while(runn){
if(i==10) break;
System.out.println("Open window and record information given! One at the time!!!");
System.out.println(" ");
giveName("test");
i++;
}
}
public void giveName(String s){
JLabel nameL = new JLabel("Give this post a name:");
JLabel searchL = new JLabel("What do you want the searchterm to be?");
wind2 = new JFrame("EazyMoney");
wind2.setLayout(new BorderLayout());
JPanel all = new JPanel();
all.setLayout(new GridLayout(2,2));
searchtermF = new JTextField(30);
nameF=new JTextField(30);
all.add(nameL);
all.add(nameF);
all.add(searchL);
all.add(searchtermF);
done = new JButton("Press when you have filled in the information!");
done.addActionListener(this);
String prn = "The post in question: " + s;
JLabel header = new JLabel(prn);
wind2.add(header, BorderLayout.NORTH);
all.setVisible(true);
wind2.add(all, BorderLayout.CENTER);
wind2.add(done, BorderLayout.SOUTH);
wind2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wind2.pack();
wind2.setLocationRelativeTo(null);
wind2.validate();
wind2.setVisible(true);
}
public void actionPerformed(ActionEvent e){
System.out.println("Action recorded, new window can now be shown. All information stored.");
System.out.println(" ");
}
}
我尝试过的解决方案是:
- 一个简单的块,执行
while(true){}
并在g.giveName()
的第一个实例被调用后将变量设置为 true。我使用ActionListener
调用一个方法,然后在提供必要的输入时再次将变量更改为 false。这导致出现一个灰色框,里面什么也没有。 - 制作一个与上面的方块相同的循环屏障。使用单独的线程调用
g.giveName()
,然后从动作侦听器调用await()
。结果同上。 - 使
readFile
由单独的线程运行并在g.giveName()
函数上调用invokeAndWait()
。给出cannot call invokeAndWait() from the EDT-thread
,即使它是从新线程运行的。
我无法给出上面实例中使用的代码示例,因为我尝试了很多不同的解决方案并且没有了。请考虑到它可能实施错误,因此可能是我问题的有效答案,即使我似乎无法让它工作!
最后说明:所有工作都可以在这里找到,如果你想测试代码: https://github.com/Robiq/EazyMoneyWork
如果您需要在同一线程上执行其他操作,避免阻塞 EDT 的方法是临时创建一个新的事件队列。这是一些示例代码。在这种情况下,它会阻止当前线程等待其他事件发出信号,但您可以将其替换为需要的任何长 运行 进程。
首先检查您是否 运行 在美国东部时间:SwingUtilities.isEventDispatchThread
。那么如果你是:
EventQueue tempEventQueue = new EventQueue();
Toolkit.getDefaultToolkit().getSystemEventQueue().push(tempEventQueue);
try {
wait();
} catch (InterruptedException ex) {
// stop waiting on interrupt
} finally {
tempEventQueue.pop();
}
模态对话框在 Swing 中的工作方式与此类似。但总的来说,这不是好的做法。更好的方法是了解要侦听哪些事件以执行特定操作。在您的情况下,用户事件不应该 'stop' 您的程序 - 它应该禁用不适当的组件,直到用户响应然后重新启用它们。