2015-01-04 135 views
0

我一直在制作一个程序,它从文件中读取数据,识别文件中的常见“帖子”,并对这些文章进行总结。我的问题是,允许用户指定帖子的名称和搜索项的GUI事件不会中断程序的运行,就像我希望的那样。在gui事件后阻塞主线程

我可以让它停止,但然后GUI将不会正确显示。我尝试了一些解决方案,这些解决方案将在帖子的底部指定。

编辑:删除codedump和补上一resembeling的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){}并设置变量设置为true后第一个g.giveName()已被调用。我使用ActionListener来调用一个方法,然后在必要的输入被赋予时再次将该变量更改为false。这导致了一个灰色的盒子,没有任何东西。
  • 制作与上述块相同的循环屏障。使用单独的线程调用g.giveName(),然后从动作侦听器中调用await()。与上述结果相同。
  • 制作readFile由一个单独的线程运行并在g.giveName()函数上调用invokeAndWait()。尽管它是从一个新线程运行的,但仍给出cannot call invokeAndWait() from the EDT-thread

我不能举出上述实例中使用的代码的例子,因为我已经尝试了很多不同的解决方案,并且没有更多。请考虑到它可能被错误地执行了,因此可能是我的问题的一个有效答案,尽管我似乎无法完成它的工作!

最后一点:所有的工作都可以在这里找到,如果你想测试代码: https://github.com/Robiq/EazyMoneyWork

+1

圣代码转储蝙蝠侠!这是太多的代码 - 太多了。从你的描述来看,它应该可以被SSCCE收录。强调第一个“S”。 – 2015-01-04 13:40:14

+0

将尝试添加,以便更有意义。尝试提出问题的更早,并被告知给出所有的代码,所以我做了... – 2015-01-04 14:07:24

+0

不要阻塞EDT(事件调度线程)。发生这种情况时,GUI将“冻结”。有关详细信息和修补程序,请参见[Swing中的并发](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/)。 – 2015-01-04 14:19:05

回答

0

,以避免阻塞EDT如果你需要执行其他东西在同一个线程是暂时的方式创建一个新的事件队列。这里是一些示例代码。在这种情况下,它会阻止当前线程等待其他事件发出信号,但您可以将其替换为需要长时间运行的进程。

首先检查您是否正在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中的工作。但总的来说这不是一个好习惯。更好的是了解要执行特定操作的哪些事件。在你的情况下,用户事件不应该“停止”你的程序 - 它应该禁用不适当的组件,直到用户作出响应,然后重新启用它们。