2010-06-03 12 views
5

Tôi có một Ứng dụng Java sử dụng SWT làm bộ công cụ và tôi cảm thấy mệt mỏi với tất cả mã bảng nồi hơi xấu xí cần để cập nhật phần tử GUI.Java SWT: gói syncExec và asyncExec để dọn sạch mã

Chỉ cần để thiết lập một nút khuyết tật để được kích hoạt Tôi phải đi qua một cái gì đó như thế này:

shell.getDisplay().asyncExec(new Runnable() { 
    public void run() { 
     buttonOk.setEnabled(true); 
    } 
}); 

Tôi muốn giữ mã nguồn của tôi như là phẳng như tôi có thể có thể, nhưng tôi cần một con số khổng lồ 3 cấp độ thụt đầu dòng chỉ để làm một cái gì đó đơn giản.

Có cách nào tôi có thể bao bọc không? Tôi muốn một lớp học như:

public class UIUpdater { 
    public static void updateUI(Shell shell, *function_ptr*) { 
     shell.getDisplay().asyncExec(new Runnable() { 
      public void run() { 
       //Execute function_ptr 
      } 
     }); 
    } 
} 

Và có thể được sử dụng như sau:

UIUpdater.updateUI(shell, buttonOk.setEnabled(true)); 

Something như thế này sẽ là tuyệt vời cho ẩn mà khủng khiếp mớ hỗn độn SWT dường như nghĩ là cần thiết để làm bất cứ điều gì.

Như tôi đã hiểu, Java không thể làm các con trỏ hàm. Nhưng Java 7 sẽ có một cái gì đó gọi là đóng cửa mà phải là những gì tôi muốn. Nhưng trong khi chờ đợi có bất cứ điều gì ở tất cả các tôi có thể làm gì để vượt qua một con trỏ hàm hoặc gọi lại đến một chức năng khác được thực hiện?

Là một sang một bên, tôi bắt đầu nghĩ rằng nó sẽ có giá trị nỗ lực để làm lại ứng dụng này trong Swing, và tôi không phải đưa lên với crap xấu xí này và không cross-platformyness của SWT.

+0

Tôi hy vọng bạn đã biết, Swing đó là đơn luồng quá. Vì vậy, bạn phải làm tương tự như trong SWT để cập nhật một phần tử GUI từ một luồng khác. Sự khác biệt duy nhất là Swing không ném một ngoại lệ khi bạn gọi phương thức Swting từ chuỗi sai. Nhưng bạn sẽ thấy maynỗi lỗi trong ứng dụng của bạn khi bạn làm điều này sai. –

Trả lời

4

Tôi gặp sự cố tương tự trong mã SWT của mình.

Tôi đã viết một lớp cơ sở không có gì ngoài các phương thức asyncExec và syncExec. Tôi đã có một phương pháp cho mọi phương pháp GUI mà tôi muốn gọi.

Lớp chủ đề không phải GUI của tôi đã mở rộng lớp cơ sở.

Vì vậy, trong lớp chủ đề phi GUI, tôi muốn có một cuộc gọi như setEnabled(shell, true)

Trong lớp cơ sở, tôi muốn xác định một phương pháp public void setEnabled(Shell shell, boolean flag) đó sẽ bao gồm các mã trong ví dụ đầu tiên của bạn.

+0

Điều này nghe có vẻ như cách duy nhất này có thể được thực hiện mà không có con trỏ chức năng và/hoặc đóng cửa. – jonescb

2

Tôi đã giải quyết điều này một thời gian trước đây trong một dự án nguồn đóng. API của tôi làm việc như thế này:

SWTUtils.asyncExec(display).on(this.getClass(), this).runInUIThread(123); 

Cuộc gọi này sẽ chạy phương pháp runInUIThread(.) trên dụ this với tham số 123. Sự lộn xộn cần thiết ở đây là tham số this.getClass().

dụ bạn lại viết:

SWTUtils.asyncExec(shell.getDisplay()).on(Button.class, buttonOk).setEnabled(true); 

thực hiện của tôi sử dụng cglib để tạo ra một proxy động cho nhóm nhất định. Proxy này được trả về bởi on(.) và cuộc gọi phương thức cũng như các tham số của nó được ghi lại và chuyển đến display.asyncExec(.). Tôi đã sử dụng Objenesis để khởi tạo proxy.

Bạn có thể ngạc nhiên rằng không có tác động hiệu suất có thể cảm nhận được. Kể từ khi proxy được lưu trữ và API phản chiếu cần thiết để gọi phương thức thực tế đã rất nhanh trong java 1.6, tôi thậm chí còn sử dụng nó cho người nghe sự kiện.

Rõ ràng đây là một giải pháp khá điên rồ;) Tôi không thể xuất bản nó, nhưng nếu bạn bực mình như tất cả những lớp bên trong vô danh này, bạn có thể muốn tìm nó. Trên thực tế nó không phải là quá nhiều mã.

2

Bạn nói rằng bạn muốn một cái gì đó như:

public class UIUpdater { 
    public static void updateUI(Shell shell, *function_ptr*) { 
     shell.getDisplay().asyncExec(new Runnable() { 
      public void run() { 
       //Execute function_ptr 
      } 
     }); 
    } 
} 

Thực tế là bạn không thể có điều này không phải là một chức năng của SWT, đó là một chức năng của Java như một ngôn ngữ lập trình. Việc thiếu các chức năng và đóng cửa cao hơn của Java ngăn cản bạn tạo một DSL tốt có thể che giấu chuyến bay đó cho bạn, vì vậy các câu trả lời khác mà bạn nhận được cũng tốt như bất kỳ trừ khi bạn thay đổi ngôn ngữ.

Bây giờ, nếu bạn đang sử dụng một ngôn ngữ như Scala chẳng hạn, tôi nghĩ câu trả lời là khác nhau nhiều. Bạn có thể tạo ra một số loại chức năng bắt chước một cấu trúc điều khiển để đảm bảo rằng các cuộc gọi SWT của bạn sẽ được thực hiện trên luồng hiển thị SWT chính.

Cái gì như:

val enabled = model.isEditable 
Swt { 
    text.setEnabled(enabled); 
    composite.refresh(); 
}