2010-04-28 35 views
19

Giả sử chúng ta có ứng dụng Swing sau:Detect nếu Java thành phần Swing đã được ẩn

final JFrame frame = new JFrame(); 

    final JPanel outer = new JPanel(); 
    frame.add(outer); 

    JComponent inner = new SomeSpecialComponent(); 
    outer.add(inner); 

Vì vậy, trong ví dụ này, chúng ta chỉ cần có một bảng điều khiển bên ngoài trong khung và một thành phần đặc biệt trong bảng điều khiển. Thành phần đặc biệt này phải làm điều gì đó khi nó được ẩn và hiển thị. Nhưng vấn đề là setVisible() được gọi trên bảng điều khiển bên ngoài chứ không phải trên thành phần đặc biệt. Vì vậy, tôi không thể ghi đè lên phương thức setVisible trong thành phần đặc biệt và tôi cũng không thể sử dụng một trình lắng nghe thành phần trên nó. Tôi có thể đăng ký người nghe trên thành phần phụ huynh nhưng nếu bảng điều khiển bên ngoài cũng nằm trong một bảng điều khiển khác và bảng điều khiển bên ngoài bên ngoài này bị ẩn?

Có giải pháp dễ dàng hơn đệ quy thêm bộ lắng nghe thành phần cho tất cả các thành phần chính để phát hiện thay đổi mức hiển thị trong SomeSpecialComponent không?

Trả lời

13

Để nghe loại sự kiện này xảy ra trong cấu trúc phân cấp, bạn có thể làm như sau.

class SomeSpecialComponent extends JComponent implements HierarchyListener { 

    private boolean amIVisible() { 
     Container c = getParent(); 
     while (c != null) 
      if (!c.isVisible()) 
       return false; 
      else 
       c = c.getParent(); 
     return true; 
    } 

    public void addNotify() { 
     super.addNotify(); 
     addHierarchyListener(this); 
    } 

    public void removeNotify() { 
     removeHierarchyListener(this); 
     super.removeNotify(); 
    } 

    public void hierarchyChanged(HierarchyEvent e) { 
     System.out.println("Am I visible? " + amIVisible()); 
    } 

} 

Bạn thậm chí có thể chính xác hơn trong việc xử lý Phân cấp cấu trúc. Có một cái nhìn tại

http://java.sun.com/javase/6/docs/api/java/awt/event/HierarchyEvent.html

3

Có một cái nhìn tại ComponentListener (hoặc ComponentAdapter)

http://java.sun.com/docs/books/tutorial/uiswing/events/componentlistener.html

http://docs.oracle.com/javase/8/docs/api/java/awt/event/ComponentListener.html

Và đặc biệt là phương pháp:

void componentHidden(ComponentEvent e) 
    Invoked when the component has been made invisible. 

Một giải pháp hoàn chỉnh sẽ giống như thế:

inner.addComponentListener(new ComponentAdapter() { 
    public void componentHidden(ComponentEvent ce) { 
     System.out.println("Component hidden!"); 
    } 
}); 

Nếu các hành động cần được thực hiện khi ẩn được kết hợp chặt chẽ với SomeSpecialCompnent, tôi khuyên bạn nên để SomeSpecialComponent triển khai ComponentListener và thêm chính nó làm trình lắng nghe cho ComponentEvents trong hàm tạo của nó.

Một cách hữu ích khác (liên quan đến thêm/xóa hoạt động và có thể không phù hợp với kịch bản cụ thể của bạn) là ghi đè addNotify()removeNotify().

+3

Sự kiện này không được kích hoạt khi phụ huynh thành phần bị ẩn, nó chỉ được kích hoạt khi phương thức setVisible() của chính thành phần đặc biệt được gọi. Như tôi đã nói, tôi đang tìm kiếm một giải pháp mà EASIER sau đó đệ quy gắn vào các sự kiện componentListener của tất cả các thành phần cha. – kayahr

+0

Tôi thấy sự cố ngay bây giờ :-) câu trả lời mới sắp tới ... – aioobe

22

Cảm ơn aioobe cho bạn answer - Tôi đến đây qua Google, tìm kiếm những điều tương tự. :-) Nó đáng chú ý là Component.isShowing() hiện công việc giống như amIVisible() của bạn mặc dù, do đó, một đoạn mã sửa đổi (kể cả một tấm séc theo tính chất của HierarchyEvent) có thể là:

class SomeSpecialComponent extends JComponent implements HierarchyListener { 

    public void addNotify() { 
     super.addNotify(); 
     addHierarchyListener(this); 
    } 

    public void removeNotify() { 
     removeHierarchyListener(this); 
     super.removeNotify(); 
    } 

    public void hierarchyChanged(HierarchyEvent e) { 
     if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) 
      System.out.println("Am I visible? " + isShowing()); 
    } 
} 
Các vấn đề liên quan