2010-08-12 30 views
6

Điều này dành cho các chuyên gia về swing. Tôi đã dành thời gian đáng kể cho vấn đề này, vì vậy nó sẽ đưa tôi một vài dòng để giải thích vấn đề.Thanh tiến trình xoay Java từ sự cố EDT

Tôi có một ứng dụng java độc lập (java 6). Trong ứng dụng của tôi, tôi có một khung với một nhóm nút radio. Tôi có một hành động được liên kết với tất cả các nút trong nhóm. Thao tác kiểm tra để xem nút radio nào được chọn và thực hiện một số thao tác. Các "công việc" liên quan đến một số tính toán nền cũng như một số bức tranh trong hai khung khác trong ứng dụng của tôi. Tính toán nền là đa luồng.

Tôi muốn hiển thị thanh tiến trình khi người dùng chọn một trong các nút radio. Tuy nhiên, khi nút radio được chọn, trong khi thao tác với nút radio đang diễn ra, thanh tiến trình sẽ không bao giờ xuất hiện. Tôi đã thử jdialog loại thanh tiến trình, tấm kính, vv Không ai trong số họ xuất hiện cho đến khi "công việc" là tất cả hoàn thành. Điều này có vẻ là vì Swing không hoàn thành việc vẽ nút radio cho đến khi "công việc" trong hành động tương ứng được hoàn thành. Và kể từ khi EDT chỉ làm một điều tại một thời điểm, hộp thoại thanh tiến trình (hoặc ngăn kính) không bao giờ được hiển thị.

Sau đó tôi đã cố gắng sử dụng SwingWorker để thực hiện tất cả "công việc" này. Bắt đầu thanh tiến trình (hoặc kích hoạt một ngăn kính), bắt đầu SwingWorker và đóng thanh tiến trình (hoặc tắt khung kính) trong phương thức done() cho SwingWorker. Điều này dường như mang lại thanh tiến trình tốt, nhưng bức tranh mà là một phần của "công việc" đôi khi không hoàn thành, để lại cho tôi một số đồ tạo tác (phương pháp paintComponent khá phức tạp, vì vậy không muốn sao chép ở đây). Các đồ tạo tác biến mất nếu tôi thay đổi kích thước cửa sổ. Trong thực tế, điều này xảy ra nếu tôi sử dụng một lớp mở rộng Thread thay vì SwingWorker. Điều này là tất cả bởi vì Swing không phải là threadsafe và tôi đang cố gắng làm công việc GUI từ một chủ đề khác với EDT. Tôi hiểu phần đó.

Tôi phải làm gì? "công việc" mất khoảng 30 giây và dường như quá dài để đi mà không hiển thị cho người dùng một số loại chỉ báo rằng chương trình đang hoạt động. Tôi cũng đã cố gắng thay đổi con trỏ đến một con trỏ chờ và đã chạy vào các vấn đề tương tự như trên. Điều duy nhất mà tôi có thể làm là tắt khung và đặt tiêu đề của khung thành một số văn bản như "đang hoạt động ..."

Bất kỳ ai đã gặp sự cố này trước đây?

Trả lời

4

Tôi nghĩ bạn có quyền làm công việc trong chuỗi SwingWorker, nhưng bạn không nên cố gắng vẽ tranh ở đó.

Tôi muốn được xu hướng:

  • Có chương trình ActionListener() thanh tiến trình, đặt ra các SwingWorker rồi thoát

  • Có các sợi nhân làm việc, và định kỳ gọi repaint() trên thành phần thanh tiến trình (điều này được đảm bảo là luồng an toàn)

  • Thanh tiến trình có riêng paintComponent (sẽ tự động được gọi trên EDT). Nếu cần thiết, điều này có thể đọc một số biến được cập nhật bởi chuỗi công nhân để đo lường tiến trình

  • Khi chuỗi công nhân kết thúc, gọi nó là invokeLater() để chạy chức năng đóng cuối cùng trên EDT. thanh tiến trình và thực hiện bất kỳ thao tác dọn dẹp liên quan đến GUI nào khác/hiển thị thông báo hoàn thành cho người dùng, v.v.

+0

Làm cách nào để đảm bảo rằng EDT không thực hiện bất kỳ bức tranh nào khác cho đến khi công việc trên luồng SwingWorker hoàn thành? Công việc có thể được thực hiện trong nền phải được hoàn thành trước khi khung hình của tôi được sơn lại. – Anu

+0

Cảm ơn bạn! Tôi đã làm việc đó. – Anu

4

Khi bạn di chuyển công việc từ EDT đến nhân viên xoay (đó là điều đúng đắn để làm), có vẻ như cả công việc lẫn bức tranh đều được chuyển đến nhân viên xoay. Bức tranh vẫn nên xảy ra trên EDT. Bạn có thể đạt được điều này bằng cách sử dụng SwingUtilities.invokeLater để gọi repaint từ chuỗi nền hoặc bằng cách sử dụng SwingWorker.publish(V...), sẽ nhận thông báo từ chuỗi công việc của bạn và hiển thị chúng trên EDT thông qua phương thức mẫu SwingWorker.process(V...) (bạn ghi đè). Ghi đè process của bạn có thể xử lý các thông báo trung gian bằng cách vẽ lại một phần của màn hình, cập nhật tiến trình hoặc thực hiện một số hành động thích hợp khác như mong muốn. Mọi thay đổi giao diện người dùng được thực hiện ở đây sẽ hiển thị mà không cần đợi phần còn lại của công việc hoàn thành.

+0

Cảm ơn, tôi đã nhận được giải pháp của Mikera, nhưng nhận xét của bạn về việc di chuyển bức tranh đến EDT cũng đã thúc đẩy cách tôi thay đổi mọi thứ! – Anu

+0

Sử dụng SwingWorker.publish() trên chuỗi công nhân là con đường để đi, tôi nghĩ vậy. – keuleJ