2011-01-20 17 views
5

Tôi có fun sau đây sẽ được thực thi bởi chuỗi gửi sự kiện không phải là sự kiện. Ở giữa chủ đề, tôi muốn có một sốLàm thế nào để nhắc một hộp thoại xác nhận ở giữa các chủ đề không gửi sự kiện

  1. Hộp xác nhận bật lên. Chủ đề tạm ngưng thực thi.
  2. Người dùng lựa chọn.
  3. Chủ đề sẽ nhận được lựa chọn và tiếp tục thực hiện.

Tuy nhiên, tôi thấy không dễ dàng thực hiện điều đó theo cách an toàn luồng, vì hộp thoại sẽ được hiển thị theo chuỗi gửi sự kiện. Tôi cố gắng

public int fun() 
{ 
    // The following code will be executed by non event dispatching thread. 
    final int choice; 
    SwingUtilities.invokeAndWait(new Runnable() { 

     @Override 
     public void run() { 
      // Error. 
      choice = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION); 
     }    
    }); 
    return choice; 
} 

Tất nhiên điều này sẽ không làm việc như choice là cuối cùng, và tôi không thể gán giá trị trả về từ hộp thoại để nó.

Cách chính xác để đạt được 3 mục tiêu trên là gì?

Trả lời

5

Các bạn đã thử:

public int fun() 
{ 
    // The following code will be executed by non event dispatching thread. 
    final int[] choice = new int[1]; 
    SwingUtilities.invokeAndWait(new Runnable() { 
     @Override 
     public void run() { 
      // Error. 
      choice[0] = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION); 
     }    
    }); 
    return choice[0]; 
} 
2
public int fun() throws InterruptedException, InvocationTargetException { 
    // The following code will be executed by non event dispatching thread. 
    ChoiceRunnable runabble = new ChoiceRunnable(); 
    SwingUtilities.invokeAndWait(runabble); 

    return runabble.choice; 
    } 

    class ChoiceRunnable implements Runnable { 
    private int choice; 

    public void run() { 
     choice = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION); 
    } 
    } 
+0

bạn không cần phải cử, không có lý do ... – bestsss

1

Có thể tôi không hiểu câu hỏi, nhưng tôi không nhận được câu trả lời một trong hai ... nếu bạn muốn các thread kêu gọi chặn trên cuộc gọi đến fun(), tại sao hiển thị JOptionPane trong một luồng (song song) mới? Điều này có đủ không?

public int fun() { 
    return JOptionPane.showConfirmDialog(null, message, title, JOptionPane.YES_NO_OPTION); 
} 

PS Bạn xác định chuỗi gửi sự kiện không phải là gì?

+1

1 Đây là giải pháp đúng. –

+0

có null, như thành phần là khó chính xác :) cũng là chính xác bởi cơ hội – bestsss

+0

@bestsss: Cung cấp 'null' cho đối số' Thành phần' là hoàn toàn ổn; trong trường hợp này, một 'Khung' mặc định được sử dụng. Xem http://download.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html –

2

Trái với niềm tin phổ biến, bạn không cần phải gửi đến chuỗi AWT (EventQueue) để hiển thị hộp thoại. Vì vậy, chỉ hiển thị nó.

Khi bạn thực hiện JOptionPane, showMessge() chuỗi của bạn (Thread.currentThread()) sẽ đợi() và hộp thoại sẽ bật lên. Sử dụng kết quả sau showMessage và bạn tốt để đi.

Như vậy:
choice = JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION);

+0

Nhưng, có an toàn khi gọi JOptionPane từ chuỗi người dùng không? http://stackoverflow.com/questions/1595744/is-joptionpane-showmessagedialog-thread-safe –

+0

Vâng, điều đó có thể có khả năng không an toàn để đặt các từ khác: bạn không chia sẻ bất kỳ đối tượng nào. AWT (hộp thoại) chính nó là chủ đề an toàn. Việc thực thi, các sự kiện, các nút, vv, được thực hiện trong luồng AWT. Như tôi đã nói, luồng hiện tại chặn cho đến khi hộp thoại đóng (đóng hộp thoại và thông báo sau(), đảm bảo tất cả các hàng rào bộ nhớ bạn có thể cần) – bestsss

+0

Tôi cũng trả lời ở đó. Về cơ bản nếu bạn cố gắng sửa đổi các hộp thoại bên ngoài các chủ đề AWT (EventQueue) thì bạn có khả năng runnig vào một cuộc đua, cũng sửa đổi khá nhiều công cụ cung cấp AWT là thread an toàn. Lưu ý, chỉ có thể có một chuỗi AWT hoạt động, mặc dù có thể có nhiều hơn một chuỗi EventQueue duy nhất đang chạy. – bestsss

1

Tôi là một chút mệt mỏi của những người nói những câu là một trong những cách này hay cách khác nhưng mà không thực sự biết những gì họ đang nói về. Tôi đến đây tự hỏi nên chạy thread JOptionPane nào nhưng tôi nhận được câu trả lời mâu thuẫn mà không có bằng chứng thực sự để hỗ trợ cho cả hai điểm. Vâng, tôi đã tự nghiên cứu và tôi cũng hài lòng với câu trả lời này vì vậy tôi sẽ chia sẻ.

Cuộc gọi đến một trong chương trình JOptionPaneXXXDialog() đang CHẶN cho đến khi người dùng chọn ok/cancel/etc. Nói chung, bạn không đặt các sự can thiệp chặn chậm như vậy vào Chủ đề sự kiện (EDT) như một quy tắc vì mọi thành phần GUI khác sẽ đóng băng. Vì vậy, một bản năng ruột để không đặt nó trên EDT là tốt, nhưng nó cũng sai. Lý do là như đã nêu bởi một số người khác, phương pháp tạo ra các thành phần GUI và điều này nên luôn luôn được thực hiện trên EDT. Nhưng những gì về việc ngăn chặn? Bạn sẽ nhận thấy rằng ngay cả khi bạn chạy nó trên EDT, nó hoạt động tốt. Lý do được tìm thấy bên trong mã nguồn. Lớp JOptionPane tạo ra một đối tượng Dialog và sau đó các cuộc gọi show() tiếp theo là dispose(), đầu tiên trong số đó là thứ chặn luồng.Nếu bạn đọc các ý kiến ​​(hoặc javadoc), bạn sẽ thấy rằng nó nói này về phương pháp:

Nếu hộp thoại là phương thức và không phải là đã có thể nhìn thấy, cuộc gọi này sẽ không trở lại cho đến khi hộp thoại được giấu bởi gọi ẩn hoặc vứt bỏ. Nó là cho phép hiển thị hộp thoại phương thức từ sự kiện gửi chủ đề vì bộ công cụ sẽ đảm bảo rằng một máy bơm sự kiện khác chạy trong khi một trong đó viện dẫn phương pháp này bị chặn.

Vì vậy, hoàn toàn an toàn khi chạy JOptionPane trên EDT mặc dù nó chặn. Rõ ràng, nó là an toàn để gọi phương thức show() của Dialog nhưng không giống với JOptionPane vì các phương thức của nó đang tạo ra các thành phần GUI, thêm người nghe, truy cập vào các thùng chứa khác khi phương thức và chặn đầu vào cho họ. muốn tất cả những điều này được thực hiện ngoài EDT vì nó không phải là chủ đề an toàn và có thể có vấn đề. Phải thừa nhận rằng, tôi chưa bao giờ thấy vấn đề khi sử dụng JOptionPane ngoài EDT và vì vậy cơ hội có vẻ thấp, nhưng họ chắc chắn nhất có thể. Thông qua một null cho container của hộp thoại và chỉ cho các đối tượng bất biến (như Strings) làm đối số cho các trường sẽ giảm đáng kể (thậm chí có thể loại bỏ xa như tôi biết). và được truy cập trong cùng một chuỗi trong khi chúng không hiển thị. Nhưng, bạn chỉ nên an toàn và đặt nó trên EDT. Nó không phải là khó khăn để gọi SwingUtilities.invokeAndWait().

0

Khởi chạy JOptionPane từ EDT và chuyển giá trị trở lại bằng FutureTask.

public int fun() 
{ 
    FutureTask<Integer> dialogTask = new FutureTask<Integer>(new Callable<Integer>() 
    { 
     @Override public Integer call() 
     { 
      return JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION); 
     } 
    }); 
    SwingUtilities.invokeLater(dialogTask); 
    int choice = dialogTask.get(); 
} 

tín dụng để jtahlborn How to pass results from EDT back to a different thread?

Các vấn đề liên quan