2017-06-14 88 views
1

這是簡化的代碼,可以通過按下我的主JFrame類中的按鈕來調用。使用此代碼,然後解除其中一個生成的對話框,導致我的Java會話中的所有活動窗口都鎖定或僅消失。多個showMessageDialogs可以擺動擺動嗎?

//Broken code 
private void buttonActionPerformed(java.awt.event.ActionEvent evt) { 
    List<JFrame> frameList = new ArrayList<>(); 
    frameList.add(new TestJFrame()); 
    frameList.add(new TestJFrame()); 

    frameList.forEach(frame -> frame.setVisible(true)); 

    frameList.forEach(frame -> { 
     SwingUtilities.invokeLater(() -> { 
      JOptionPane.showMessageDialog(frame, "Msg", "Title", 0); 
      frame.setVisible(false); 
      frame.dispose(); 
     }); 
    }); 
} 

但是,如果我要刪除SwingUtilities.invokeLater()部分,然後它就像我預料(彈出對話框,關閉對話框,窗口消失了,重複)。

//Working code 
private void buttonActionPerformed(java.awt.event.ActionEvent evt) { 
    List<JFrame> frameList = new ArrayList<>(); 
    frameList.add(new TestJFrame()); 
    frameList.add(new TestJFrame()); 

    frameList.forEach(frame -> frame.setVisible(true)); 

    frameList.forEach(frame -> { 
     //SwingUtilities.invokeLater(() -> { 
      JOptionPane.showMessageDialog(frame, "Msg", "Title", 0); 
      frame.setVisible(false); 
      frame.dispose(); 
     //}); 
    }); 
} 

我寧可不使用第二個,因爲實際的代碼是在被告知一組聽衆的後臺線程正在啓​​動,所以如果我是使用第二個話,那就堵了線程和減慢監聽器,直到用戶響應(當我可以在那段時間處理時)。 invokeLater()怎麼樣打破了我?這是預期的行爲?

注:這是簡化代碼掏出我如何真正使用它,但核心問題依然存在(我有多個JFrame秒,如果多個JOptionPane.showMessageDialog()小號被提上invokeLater() S代表不同的JFrame當時的它我測試了上面的代碼,並在Netbeans中創建了一個新的,分離的JFrame類,並且能夠重現錯誤。 Linux。

回答

0

這很可能是invokeLater()這是破壞你的代碼。如果你想線程這個動作嘗試使用一個簡單的線程或

EventQueue.invokeLater(new Runnable() 
    { 
      public void run() 
      { //Your joptionpane here 
      } 
    });` 
+0

根據揮杆文件,'從1.3版本開始,此方法只覆蓋了java.awt.EventQueue.invokeLater()' ,所以我不明白這將如何解決任何問題?我不能只使用簡單的線程,因爲圖形相關事件需要在EDT上發生。 – billie

+0

是的,他們都應該固有工作相同,但你永遠不知道。至於簡單的線程在某些情況下,您可以使用一個ex。 JTextArea和做GIF動畫。嘗試使用SwingWorker作爲EDT [SwingWorker](https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html) – Pierre97

+0

'EventQueue.invokeLater()'的結果與' SwingUtilities.invokeLater()'。 '新的SwingWorker(){...} .execute()'也以類似的方式失敗,只是有一些額外的重繪失敗。 – billie

0

改爲調用後,我更喜歡使用 1)簡單的線程 2)的TimerTask 3)ScheduledExecutorService的

使用以下方法之一。 這是使用計時器任務

import java.util.Timer; 
import java.util.TimerTask; 
public class Task2 { 
    public static void main(String[] args) { 
    TimerTask task = new TimerTask() { 
     @Override 
     public void run() { 
     // task to run goes here 
     System.out.println("Hello !!!"); 
     } 
    }; 
    Timer timer = new Timer(); 
    long delay = 0; 
    long intevalPeriod = 1 * 1000; 
    // schedules the task to be run in an interval 
    timer.scheduleAtFixedRate(task, delay, 
          intevalPeriod); 
    } // end of main 
} 

如果您不滿意,您可以使用以後調用的例子。 但請記住永遠不要使用invoke並等待它的一個壞主意

+1

這是一個不知情的答案,不適合Swing,不適合我的問題,並且不能解決我的問題。線程推薦和關於'invokeLater'的簡單錯誤陳述。 https://stackoverflow.com/questions/5499921/invokeandwait-method-in-swingutilities。 – billie

0

這裏是我的方法,因爲我的理解問題是鎖定的窗口,它正在等待事件完成,在擺動事件與AWT有關-EventQueue。

這裏是關於做一點解釋:https://stackoverflow.com/a/22534931/1670134

因此,爲了得到你的窗口工作,我所使用的將來類型:

從Java文檔:

Future表示的異步計算的結果。提供方法 以檢查計算是否完成,等待其完成,並檢索計算結果。 的結果只能在計算完成時使用get方法獲取,如果需要,則在需要時進行阻塞,直到準備就緒。

package com.stackoverflow.future; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 

import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

import com.stackoverflow.frame.MyFrame; 

public class MySwingWorker extends SwingWorker<Void, Void>{ 

    @Override 
    protected Void doInBackground() throws Exception { 
     final ExecutorService service = Executors.newFixedThreadPool(1); 
     List<Future<JFrame>> frameList = new ArrayList<Future<JFrame>>(); 
     frameList.add(service.submit(new SwingLoader(new MyFrame()))); 
     frameList.add(service.submit(new SwingLoader(new MyFrame()))); 

     try { 
      service.shutdown(); 
      service.awaitTermination(5, TimeUnit.SECONDS); 
     } catch (InterruptedException ex) { 
      ex.printStackTrace(); 
     } finally { 
      service.shutdownNow(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     MySwingWorker mySwingWorker = new MySwingWorker(); 
     SwingUtilities.invokeLater(mySwingWorker); 
    } 

} 

裝載機:

package com.stackoverflow.future; 

import java.util.concurrent.Callable; 

import javax.swing.JFrame; 

public class SwingLoader implements Callable<JFrame>{ 

    private JFrame frame; 

    public SwingLoader(JFrame frame){ 
     this.frame = frame; 
    } 

    @Override 
    public JFrame call() throws Exception { 
     frame.setVisible(true); 
     return frame; 
    } 

} 

注:此代碼只是一個原型,爲您提供思路和必須進行修改,爲了達到理想的效果清洗。

給你一對夫婦及各類型的說明的鏈接: http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

+0

據我瞭解你的解決方案,你根本不明白這個問題。問題是我上面的發佈代碼導​​致模態對話框互相干擾。使用模態對話框應阻止用戶與被鎖定的對話框進行交互,直至其被解除。出於某種原因,解除一個模式對話框會解除它們,但它只會釋放模式對話框中的一個鎖,導致所有應用程序鎖定。我在問爲什麼。你的代碼甚至不是線程安全的。 – billie