2010-12-10 34 views
5

Tôi có ứng dụng gui ngân hàng mà tôi hiện đang làm việc và dường như có vấn đề với phương pháp setvisible cho jdialog của tôi. Sau khi người dùng đã rút một số tiền hợp lệ, tôi bật lên một hộp thoại đơn giản cho biết "giao dịch đang diễn ra". Trong phương pháp dobackground của tôi, tôi tiếp tục bỏ phiếu để kiểm tra xem giao dịch đã được nhận chưa. Tôi đã thử sử dụng swingworker và tôi không hiểu tại sao nó không hoạt động. Nếu tôi loại bỏ các cuộc gọi vô hình nó hoạt động tốt, vậy tại sao không thể làm cho hệ thống bị treo? Đây là mã nằm bên trong jbutton mouselistener của tôi:phương pháp vô hình trong hệ thống treo java swing

SwingWorker<String,Integer> worker = new SwingWorker<String,Integer>(){ 

    JDialog waitForTrans = new JDialog((JFrame)null,true); 
    public String doInBackground() throws Exception { 
    waitForTrans.add(new JLabel("Updating balance in system. Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300,100)); 
    waitForTrans.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    waitForTrans.setVisible(true); 
    Bank.getInstance().sendTransaction(currentPin,"-"+withdraw); 
    while(!Bank.getInstance().hasCompletedTransaction){ 

    } 
    return null; 

    } 

    public void done(){ 
    try { 
     this.get(); 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 

     e.printStackTrace(); 
    } 
    waitForTrans.setVisible(false); 
    newField.setText(String.valueOf(Bank.getInstance().getAccountList().get(currentPin).getBalance())); 
    } 

}; 
worker.execute(); 
+0

Phiên bản java nào bạn đã thấy chặn này? Chúng tôi đã nâng cấp từ java 6 lên java 8 và có thể đang chạy vào hành vi này. – simgineer

Trả lời

13

Trước tiên, bạn nên thực hiện tất cả các cập nhật GUI trong chuỗi Sự kiện-Công văn Swing, tức là sử dụng lớp SwingUtilites.

Thứ hai, JDialog là phương thức và do đó chặn luồng trong đó phương thức setVisible(true) được gọi (trong trường hợp của bạn là Chủ đề chính, trong trường hợp sau là Chủ đề sự kiện Swing).

tôi không nói đoạn mã sau là hoàn hảo, nhưng nó phải đưa bạn trên đường đua ...

 

final JDialog waitForTrans = new JDialog((JFrame) null, true); 

SwingWorker worker = new SwingWorker() { 

    public String doInBackground() throws Exception { 
    Thread.sleep(5000); 
    return null; 
    } 

    public void done() { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     waitForTrans.setVisible(false); 
     waitForTrans.dispose(); 
     } 
    }); 
    } 

}; 

worker.execute(); 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    waitForTrans.add(new JLabel("Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300, 100)); 
    waitForTrans.setVisible(true); 
    } 
}); 
 

Hope this helps.

+0

Cảm ơn bạn đã phản hồi nhanh! Tôi vẫn còn một chút run rẩy về các loại khía cạnh này để lập trình gui nhưng tôi nhận được nó cho hầu hết các phần bây giờ ... – Adith

+0

Hiểu cách Swing Thread-Dispatch Thread hoạt động và cách sử dụng nó đúng cách là phần khó nhất của giao diện Swing cho tôi. Hãy dành thời gian của bạn và làm cho nó đúng, nó sẽ giúp bạn tiết kiệm rất nhiều rắc rối sau này. –

+1

Phương thức thực hiện được thực thi trên Thread Dispatch Thread vì vậy tôi không nghĩ rằng bạn cần sử dụng SwingUtilities.invokeLater trong phương thức đó. Xem http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#done%28%29 – Ryan

5

Bạn đang hiển thị hộp thoại phương thức để mã nền không thể thực thi cho đến khi hộp thoại đóng.

Thêm câu lệnh System.out.println (...) sau setVisible và bạn sẽ thấy nó không bao giờ thực thi.

+0

Tôi thấy quan điểm của bạn. Cảm ơn đã giúp đỡ. – Adith

0

camickr cung cấp cho bạn câu trả lời chính xác. Tôi muốn thêm rằng bạn có thể không sửa đổi giao diện người dùng bên ngoài Chủ đề công văn sự kiện (như bạn làm trong #doInBackground), Swing là một luồng đơn vi phạm quy tắc này có thể dẫn đến lỗi rất khó và những điều lạ trong giao diện người dùng của bạn.

1

setVisible là một phương pháp ảnh hưởng đến GUI, làm cho nội dung nào đó được hiển thị (và trong trường hợp của một hộp thoại giống như của bạn, hãy chặn cho đến khi hộp thoại đóng). Nó (giống như tất cả mọi thứ khác mà sửa đổi giao diện người dùng có thể nhìn thấy) nên không bao giờ được gọi ngoại trừ trên chuỗi gửi sự kiện Swing. Bạn đang gọi nó từ phương pháp doInBackground của SwingWorker, chạy trên một chuỗi nền.

Những gì bạn cần phải làm gì để khắc phục điều này là làm cho waitForClose thoại một biến final mà bạn tạo ra trước khi gọi execute trên SwingWorker và sau đó gọi setVisible trên ngay lập tức sau khi bắt người lao động.

final JDialog waitForTrans = ... 
// set up the dialog here 

SwingWorker<String, Integer> worker = new SwingWorker<String, Integer>() { 
    ... 
}; 
worker.execute(); // start the background process 

waitForTrans.setVisible(true); // show the dialog 

Bạn cần thực hiện theo thứ tự này bởi vì nếu không hộp thoại phương thức sẽ chặn bạn bắt đầu công nhân.

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