2015-01-04 133 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中的工作。但總的來說這不是一個好習慣。更好的是瞭解要執行特定操作的哪些事件。在你的情況下,用戶事件不應該「停止」你的程序 - 它應該禁用不適當的組件,直到用戶作出響應,然後重新啓用它們。