2012-09-16 27 views
7

Tôi có bộ hẹn giờ Đu (javax.swing.Timer) được sử dụng để thực hiện một số hoạt ảnh trong một thành phần Swing tùy chỉnh.Dừng bộ hẹn giờ Swing khi một thành phần bị ẩn

Tuy nhiên, điều này đang gây ra sự cố - đặc biệt là dường như dừng ứng dụng chấm dứt do chuỗi hẹn giờ trực tiếp ngay cả sau khi tất cả các cửa sổ được đóng lại. Ngoài ra nó sẽ được tốt đẹp để tránh các chi phí của bộ đếm thời gian chạy trên các đối tượng ẩn khi các hình ảnh động không thể được nhìn thấy.

Lý tưởng nhất là tôi muốn làm như sau:

  • Dừng bộ đếm thời gian khi các thành phần được ẩn
  • Bắt đầu thời gian một lần nữa bất cứ khi nào các thành phần trở nên rõ ràng

Đây có phải là có thể làm (theo một cách an toàn theo chủ đề!)

+4

hmm .. có gì sai với một ancestorListener (đó sẽ là suy nghĩ đầu tiên của tôi)? – kleopatra

+0

Hoặc bạn có thể thêm một [ComponentListener] (http://docs.oracle.com/javase/7/docs/api/java/awt/event/ComponentListener.html) vào nó và thêm ** timer.start()/stop() bên trong nó là các phương thức componentHidden (...) và componentShown (...) ** –

+1

@GagandeepBalin một componentListener chỉ là một loại propertyChangeListener với thuộc tính có thể nhìn thấy của một thành phần, mà không thay đổi nếu fitổ tiên được ẩn/hiển thị. – kleopatra

Trả lời

5

Tôi hoài nghi về tiền đề đầu tiên của bạn: đơn giản này counter-example cho thấy rằng đang chạy javax.swing.Timer không loại trừ EXIT_ON_CLOSE. Gói riêng tư, được chia sẻ javax.swing.TimerQueue bắt đầu chuỗi daemon, cho phép Program Exit. Bạn có thể dễ dàng miễn cưỡng với dựa vào chi tiết triển khai này, nhưng có thể đáng tìm kiếm một lý do khác khiến chương trình của bạn không thoát được.

Nếu trì hoãn @kleopatra trên AncestorListener; nó sẽ cho phép bạn kiểm soát Timer như mong muốn. Chu kỳ nhiệm vụ của hoạt ảnh thành phần là điển hình khá sáng và thường bị chi phối bởi việc hiển thị; chi phí của thứ hai là nhỏ khi thành phần không nhìn thấy được. Nó có thể có giá trị profiling để xác minh rằng tối ưu hóa đề xuất là giá trị nỗ lực. Nếu vậy, hãy xem xét WindowListener để giảm thiểu hoạt động trong cửa sổ không hoạt động hoặc được biểu tượng hóa.

Phụ lục: Câu trả lời bị xóa hiện được đề xuất ghi đè setVisible() để điều chỉnh bộ hẹn giờ. Trong khi bề ngoài hấp dẫn, cách tiếp cận là giòn và quy mô kém. Cách tiếp cận người nghe thúc đẩy các observer pattern thường được sử dụng trong Swing architecture.

+0

Cảm ơn, phương pháp này hoạt động tốt (thực ra tôi đã sử dụng HeirarchyListener để có thể bắt được một số sự kiện khác nhưng tôi nghĩ nguyên tắc là như nhau). Tôi cũng nghĩ rằng bạn cũng đúng trên giờ, nhưng như bạn nói nó có thể là tốt nhất không dựa vào hành vi đó! – mikera

+1

Để tham khảo, đây là [ví dụ] có liên quan (http://stackoverflow.com/q/10880326/230513) so sánh ba trình nghe được đề cập. – trashgod

1

Hàng đợi sự kiện phải yên lặng trong một giây để tắt máy. Đó là một giá trị mã hóa cứng trong lớp AWTAutoShutdown.

Vì vậy, nếu bộ hẹn giờ xoay của bạn tiếp tục tạo sự kiện, cách nhau ít hơn một giây, điều đó sẽ khiến ứng dụng không bị chấm dứt.

Hãy xem ví dụ này (bên dưới). Nó sẽ không chấm dứt, bởi vì các chủ đề, mặc dù nó được đánh dấu là deamon, tiếp tục thêm các sự kiện vào hàng đợi. Nếu chúng ta tăng giấc ngủ lên 1500 (1,5 giây) - nó sẽ chấm dứt hạnh phúc.

public static void main(String[] args) 
{ 
    Thread thread = new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      while (true) 
      { 
       // Submit an empty event to the queue 
       EventQueue.invokeLater(new Runnable() 
       { 
        @Override 
        public void run() 
        { 
        } 
       }); 
       try 
       { 
        Thread.sleep(500); 
       } 
       catch (InterruptedException e) 
       { 
        throw new IllegalStateException(e); 
       } 
      } 
     } 
    }); 
    thread.setDaemon(true); 
    thread.start(); 
} 
1

Chúng tôi làm điều đó như thế này:

private static final class DisplayabilityListener implements HierarchyListener { 
    private final JComponent component; 
    private final Timer timer; 

    private DisplayabilityListener(JComponent component, Timer timer) { 
    this.component = component; 
    this.timer = timer; 
    } 

    @Override 
    public void hierarchyChanged(HierarchyEvent e) { 
    if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) > 0) { 
     if (component.isDisplayable()) { 
      timer.start(); 
     } else { 
      timer.stop(); 
     } 
    } 
    } 

}

+0

Tôi sẽ thay đổi 'if ((x & y)> 0)' thành 'if ((x & y)! = 0)', vì nó sẽ không hoạt động nếu 'y' có bộ MSB của nó. – Matthieu

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