2012-11-19 76 views
5

Tôi có một mã như thế:repaint() trong Java không "vẽ lại" ngay lập tức?

// In MyPanel.java 
public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g); 
    // Draw something 
    mypanel_count++; 
} 

// In Test.java 
public void testLargeData() 
{ 
    while (notDone) 
    { 
     panel.repaint(); 
     // do huge work 
     test_count++; 
     System.out.println("Test_count: " + test_count + ", MyPanel_count: " + mypanel_count); 
    } 
} 

// Output !!! 
Test_count: 752, MyPanel_count: 23 
Test_count: 753, MyPanel_count: 23 
Test_count: 754, MyPanel_count: 23 
Test_count: 755, MyPanel_count: 24 

Nhưng khi tôi thay đổi panel.repaint() để panel.paintComponent(panel.getGraphics()) thì ra là đúng:

Test_count: 752, MyPanel_count: 752 
Test_count: 753, MyPanel_count: 753 
Test_count: 754, MyPanel_count: 754 
Test_count: 755, MyPanel_count: 755 

Tại sao? paintComponent phương pháp hoạt động, nhưng đôi khi nó mù, vì vậy tôi không muốn sử dụng nó. Bất kỳ ai cũng có thể cho tôi một số gợi ý? Cảm ơn!

+0

http://stackoverflow.com/questions/9389187/difference-between-paint-paintcomponent-and-paintcomponents-in-swing. – Raghunandan

+0

@Raghunandan: cảm ơn câu trả lời của bạn, nhưng đó không phải là rắc rối của tôi. –

+0

bạn đã thử [JComponent.html # paintImmediately (int, int, int, int)] (http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#paintImmediately%28int ,% 20int,% 20int,% 20int% 29) – mKorbel

Trả lời

9

Nếu bạn đọc tài liệu của repaint một cách cẩn thận, bạn sẽ thấy rằng nó nói rằng (nhấn mạnh mỏ):

Nếu thành phần này là một thành phần nhẹ, phương pháp này gây ra một phương pháp sơn của thành phần này càng sớm càng tốt. Nếu không, phương pháp này sẽ thực hiện cuộc gọi đến phương thức cập nhật của thành phần này ngay sau có thể.

Điều này có nghĩa là AWT/Swing được phép tối ưu hóa việc sơn lại bằng cách hợp nhất các bản sao được yêu cầu liên tiếp nhanh chóng. Ngoài ra còn có phương thức repaint(long time), cho phép bạn kiểm soát thời gian AWT/Swing được phép đợi với yêu cầu đầy đủ của bạn. Nó vẫn có thể hợp nhất các yêu cầu mặc dù, đặc biệt nếu bạn làm chúng trong một vòng lặp.

Có thể hữu ích khi đọc bài viết "Painting in AWT and Swing", cố gắng giải thích các khái niệm khác nhau có liên quan.

Để làm cho bảng điều khiển được sơn lại cho mỗi lần lặp lại, bạn sẽ phải đợi sơn để xảy ra và sau đó tiếp tục với vòng lặp của bạn. Điều này có nghĩa là bạn cần một số đồng bộ hóa giữa chuỗi xử lý của bạn (vòng lặp) và chuỗi AWT/Swing. Như một ý tưởng thô, bạn có thể ví dụ wait() trên đối tượng bảng điều khiển ở cuối vòng lặp của bạn nếu nó chưa được sơn lại kể từ lần gọi cuối cùng đến số repaint() và gọi notifyAll() ở cuối phương thức paintComponent() của bảng điều khiển. Tuy nhiên, điều này có thể khó thực hiện đúng, vì vậy bạn chỉ nên thực hiện việc này nếu bạn thực sự cần vẽ lại thành phần của mình trong thời gian thực. Là một thay thế, paintImmediately(...) có thể được sử dụng, nhưng bạn sẽ phải làm tất cả những xử lý của bạn trong trường hợp dispatching thread, như thế này:

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     while(notDone) { 
      // Do your processing 
      panel.paintImmediately(...); 
     } 
    } 
}); 

Lưu ý rằng điều này sẽ ngăn chặn bất cứ xử lý sự kiện bao gồm chuột và bàn phím đầu vào từ đang được xử lý trong khi vòng lặp của bạn đang chạy. Bạn có thể đọc thêm về Swing and Threading trong "Concurrency in Swing"

0

hiểu rằng bạn không có quyền kiểm soát hoàn toàn nếu hoặc khi sơn (...) nhận được gọi là, và rằng repaint() cuộc gọi chỉ là một gợi ý để JVM để vẽ. Nếu quá nhiều repaint() yêu cầu này đến trong và họ chồng lên như bạn đang làm, sau đó họ sẽ được kết hợp

tham khảo: https://stackoverflow.com/a/13256847/1423083

1

Như câu trả lời khác cho biết: đó là vấn đề khi AWT gọi paint().

Nếu bạn thực hiện một số công việc cần thông tin từ các thành phần được vẽ/bố cục, điều gì cũng giúp đưa công việc này vào một chuỗi công nhân chờ cho đến khi bức tranh hoàn tất.

Trong trường hợp của bạn đó sẽ là một cái gì đó như:

panel.repaint(); 

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     // do huge work 
     test_count++; 
     System.out.println("Test_count: " + test_count 
      + ", MyPanel_count: " + mypanel_count); 
    } 
}); 

Mặc dù tôi không chắc chắn làm thế nào nó sẽ cư xử theo while vòng lặp của bạn.

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