2011-01-04 38 views
5

Tôi thường sử dụng SwingUtilities.invokeLater(). Tuy nhiên, làm như vậy sẽ gây khó khăn cho việc gỡ lỗi trong một số trường hợp nhất định: bạn không thể nhìn thấy dấu vết ngăn xếp của mã được gọi là SwingUtilities.invokeLater(), bởi vì mã đó đã kết thúc thực thi.Java: gỡ lỗi bằng SwingUtilities.invokeLater()

Có đề xuất nào về cách đặt một số loại ngữ cảnh (chỉ cho mục đích gỡ lỗi) khi gọi SwingUtilities.invokeLater(), để bạn có thể tìm ra nguyên nhân gây ra sự kiện giao diện người dùng được đề cập?

+1

Bạn có tìm thấy bất kỳ giải pháp chấp nhận được?Thực sự quan tâm để biết những gì bạn cuối cùng đã làm :) – Twister

Trả lời

1

Ghi đè phương thức, thêm cuộc gọi Nhật ký và sau đó gọi một cuộc gọi thực ... Lưu ý: bạn phải thay thế tất cả các cuộc gọi của mình sang phương thức gốc.

Bạn thậm chí có thể bọc runnable và thêm một số bối cảnh (ví dụ như dấu thời gian của cuộc gọi để gọi sau). Khi bắt đầu Runnable nó bắt đầu bằng chữ in số bối cảnh

public static void myInvokeLater(final Runnable runnable) { 
    long ts = System.currentTimeMillis(); 
    Log.info("call to invoke later, context :" + ts); 
    Runnable r = new Runnable() { 
      public void run() { 
       Log.info("start runnable of invokeLater with context :" + ts); 
       runnable.run(); 
      } 
     }; 
    SwingUtilities.invokeLater(r); 
} 
+0

Nếu bạn System.out.println (runnable) và System.out.println (điều này) trong các phương pháp chạy của runnable, bạn sẽ có thể phù hợp với họ lên :) –

+0

không System.out.println vui lòng! –

+0

Và không dễ dàng vô hiệu hóa. ở đó bạn chỉ có thể thêm nếu (DEBUG) sau đó làm phép thuật, khác chỉ cần chuyển tiếp đến InvokeLater thực. – Twister

1

tôi sẽ có xu hướng thay thế swingUtilites "tiêu chuẩn" phương pháp # invokeLater bởi một tiên tiến hơn, có thể nhúng vào một số "localUtilities", mà bạn cung cấp cho cả hai mã để thực hiện với, như một đối số, sự kiện nguồn hoặc một bản sao chủ đề an toàn của nó (tôi đoán bạn có một sự kiện nguồn, bất kể kiểu của nó là gì).

1

Nếu bạn đang gọi invokeLater thường xuyên, bạn có thể muốn xem xét việc đơn giản hóa luồng của mình.

invokeLater đang sử dụng hiệu quả các số liệu thống kê có thể thay đổi và do đó là xấu xa nhất. Thử nghiệm và nhiều tính năng khác sẽ trở nên dễ dàng hơn nếu bạn chuyển từ gọi số EventQueue.invokeLater sang sử dụng giao diện với invokeLaterisDispatchThread.

Thật không may là bạn không thể thay thế các số invokeLaterisDispatchThread được sử dụng bởi các thư viện.

+0

Bạn có thể giải thích nhận xét của mình về "statics có thể thay đổi" không? Tôi không thấy bất kỳ lý do nào khiến bạn cần chuyển dữ liệu có thể thay đổi qua ranh giới UI/non-UI. – Anon

+0

@Anon Việc thực hiện tĩnh 'invokeLater' phải chọn một hàng đợi sự kiện tĩnh [có thể thay đổi] ở đâu đó dọc theo dòng. –

+0

Vì vậy, bạn đang đề xuất thay thế các cuộc gọi tĩnh thành 'SwingUtilities' bằng một phiên bản (được tiêm)? – Anon

2

Hầu hết các câu trả lời khác ở đây đều tốt, nhưng tôi muốn thêm đề xuất khác. Nếu bạn đang gọi SwingUtilities.invokeLater rất thường xuyên, có thể bạn đang thực hiện nó một cách không cần thiết trong một khoảng thời gian, đặc biệt nếu mục đích duy nhất của cuộc gọi là đảm bảo rằng các thay đổi Swing được thực hiện trên chuỗi sự kiện. Hãy thử điều này khi thích hợp:

if (SwingUtilities.isEventDispatchThread()) { 
    myRunnable.run(); 
} else { 
    SwingUtilities.invokeLater(myRunnable); 
} 
+0

Vì vậy SwingUtilities đã không làm điều này như là một phần của việc thực hiện invokeLater() của nó? –

+0

Không, bởi vì invokeLater chỉ thực hiện 'sau', sau khi tất cả các sự kiện đang chờ xử lý đã được xử lý. Rõ ràng nếu bạn cần hành vi đó bạn không thể sử dụng thủ thuật này. invokeAndWait cũng có thể hoạt động như một giải pháp thay thế. – DJClayworth

1

Bạn có đang vô danh Runnable s đến invokeLater()?

Nếu có, tôi khuyên bạn nên thay thế chúng bằng các lớp không ẩn danh, sẽ thêm một vài dòng mã, nhưng sẽ cung cấp cho bạn ít nhất một số cấp truy nguyên (ví dụ: TableUpdateFromQuery). Điều này hoạt động tốt nhất nếu bạn gọi một loại cập nhật cụ thể chỉ từ một nơi trong ứng dụng. Nó cũng dẫn bạn xuống con đường của "hoạt động nền", có thể được kiểm tra bên ngoài giao diện người dùng.

2

Bạn có thể thử ghi đè EventQueue và in stacktrace cho các sự kiện đã đăng. Cũng trong ví dụ dưới đây, một số duy nhất sẽ được gán cho mỗi sự kiện được đăng. Khi invokeLater sẽ được gọi từ khác invokeLater thì văn bản postEvent 9 from 7 sẽ được in trong bản ghi

  // Place this code somewhere in the main class to override queue 
     EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); 
     eventQueue.push(new MyEventQueue()); 

đâu lớp MyEventQueue có thể trông như thế này:

import java.awt.AWTEvent; 
import java.awt.EventQueue; 
import java.awt.event.InvocationEvent; 
import java.util.WeakHashMap; 

public class MyEventQueue extends EventQueue { 

    int currentNumber = 0; 
    WeakHashMap<AWTEvent,Integer> eventIdMap = new WeakHashMap<AWTEvent,Integer>(); 
    AWTEvent currentEvent = null; 

    protected void dispatchEvent(AWTEvent event) { 
     if (event instanceof InvocationEvent) { 
      currentEvent = event; 
     } 
     super.dispatchEvent(event); 
     currentEvent = null; 
    } 

    public void postEvent(AWTEvent event) { 
     if (event instanceof InvocationEvent) { 
      currentNumber = currentNumber + 1; 
      eventIdMap.put(event, currentNumber); 
      System.out.println("postEvent " + currentNumber + " " + 
        (currentEvent != null ? "from " + eventIdMap.get(currentEvent) : "")); 
      for(StackTraceElement element : new RuntimeException().getStackTrace()) { 
       System.out.println("\t" + element); 
      } 
     } 
     super.postEvent(event); 
    } 
} 
+0

Làm rõ, một 'mở rộng EventQueue' và ghi đè phương thức mong muốn, ví dụ: 'invokeLater()'. Dưới đây là ví dụ có liên quan, http://stackoverflow.com/questions/3158409 – trashgod

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