//--------------------------------------------------------
   아래의 환경에서 작성된 글입니다.

   java version "1.4.2_03"
   Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
   Java HotSpot(TM) Client VM (build 1.4.2_03-b02, mixed mode)

   작성자 : Ye@ori.S@eo@gmail.com ( @@ 제거)
   일   자 : 2004 년 1월 27일
//----------------------------------------------------------//

ContainerListener : 컨테이너에 컴포넌트가 추가, 삭제되었음을 알려주는 이벤트를 청취한다.

추가할 때는

       
public Component add(Component comp)
        public Component add(Component comp, int index)  
        public void add(Component comp, Object constraints)
        public void add(Component comp, Object constraints, int index)

를 이용한다. 여기서 위의 add 메소드들은 Container 클래스에서

       
protected void addImpl(Component comp, Object constraints, int index)

를 실행하게 된다. 위의 메소드의 중요한 부분을 살펴보면 다음과 같다.

       
if (comp instanceof Container) {
            for (Container cn = this; cn != null; cn=cn.parent) {
                if (cn == comp) {
                throw new IllegalArgumentException(
                      "adding container's parent to itself");
                }
            }
            if (comp instanceof Window) {
                throw new IllegalArgumentException(
                       "adding a window to a container");
            }
        }

컨 테이너에 삽입될 컴포넌트가 Container 라면, 자기 자신에게 포함시키려고 시도하지 않는지를 살펴본다. 만일 그렇다면 예외를 던지고 add 는 종료된다. 또한 Window 는 다른 Container에 포함되지 않음을 보여준다.

다음 코드는 하나의 컴포넌트는 항상 하나의 parent 를 갖음을 보여준다.

        
/* Reparent the component and tidy up the tree's state. */
            if (comp.parent != null) {
                comp.parent.remove(comp);// 부모가 있으면 부모의 리스트에서 삭제한다.
                    if (index > ncomponents) {
                        throw new IllegalArgumentException("illegal component position");
                    }
            }

컴포넌트를 삽입 한 후에 그 결과가 바로 화면에 보여지지 않는다. 왜냐하면 메소드 안에서

           if (valid) {invalidate();    }

자동으로
invalidate() 를 실행하기 때문이다. 일단 invalidate() 가 호출되면 컴포넌트가 추가되는 컨테이너의 Layout 은 무효화 된다. 현재 새로 추가된 컴포넌트를 어디에 배치해야 할지 모르는 상황이기 때문에 이렇게 Layout 을 무효화 한 후에 컴포넌트를 고려해서 새롭게 Layout을 설정한다.

Layout 을 LayoutManager 에 추가한 후에 새롭게 validate(); 하는 것은 사용자의 몫이다.

따 라서, Container에 Component 를 추가 한 후에는 반드시 validate(); 를 호출해야만 결과를 화면에서 볼 수 있다. (그렇지 않다면 사용자가 창을 resizing 하는 등 repaint() 를 일으킬만한 행위를 사용자가 해주어야만 화면에 나타날 것이다.)

삭제할때는

       
public void remove(Component comp);
        public void remove(int index);
        public void removeAll();

를 이용한다.  삭제를 실행하면 삭제될 컴포넌트의 removeNotify() 가 내부에서 호출된다.(따라서 별도로 호출할 필요가 없다.). 그리고나서 Container 의 LayoutManager 에서도 해당 컴포넌트를 제거하고 컴포넌트가 현재의 Container 에 가지고 있는 참조를 null 로 만든다.( 위에서 컴포넌트가 컨테이너에 삽입될 때 컨테이너를 자신의 parent 로 참조를 연결하는 부분이 있었다. 여기서는 그 연결을 끊는 것이다.)

그리고 ContainerEvent 를 생성해서 EventQueue 에 넣는다.

         
 if (containerListener != null ||
                (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                ContainerEvent e = new ContainerEvent(this,
                                     ContainerEvent.COMPONENT_REMOVED,
                                     comp);
                dispatchEvent(e);
            }

만일 자신의 컴포넌트를 제거하는 컨테이너가 ContainerListener 를 구현하고 있다면 여기서 생성한 이벤트를 청취하고 적절한 행동을 하게 된다.

아래의 코드는 삽입, 삭제에 관한 간단한 예제이다.



import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class PanelExchangeTest extends Applet implements ActionListener, ContainerListener
{
        boolean type = true;
        Panel panel02;
        Button add, remove;
        public void init()
        {
                setLayout(new BorderLayout());
                panel02 = new Panel(new FlowLayout());
               
                Button button03 = new Button("Button 03");
                Button button04 = new Button("Button 04");
               
                panel02.add(button03);
                panel02.add(button04);
               
                add = new Button("add");
                remove = new Button("remove");
        }

        public void start()
        {
               
panel02.addContainerListener(this);
                remove.addActionListener(this);
                remove.setActionCommand("del");
                add.addActionListener(this);
                add.setActionCommand("add");
                Panel p = new Panel();
                p.add(add);
                p.add(remove);
                add(panel02, "Center");
                add(p, "South");
        }
       
        public void actionPerformed(ActionEvent e)
        {
                String cmd = e.getActionCommand();
               
                if ( cmd.equals("add"))
                {
                       
panel02.invalidate();
                        panel02.add(new Button("new"+panel02.getComponentCount()), panel02.getComponentCount());
                        remove.setEnabled(true);
                }
                else if ( cmd.equals("del"))
                {
                       
panel02.invalidate();
                        panel02.remove(0);
                        if ( panel02.getComponentCount() == 0 )
                                remove.setEnabled(false);
                }
               
panel02.validate(); // 항상 적어주는 것이 안전하다.
        }
       
        public void stop()
        {
                ;
        }
       
        public void destroy()
        {
                ;
        }
       
       
// 구현된 리스너 메소드
        public void componentRemoved(ContainerEvent e)
        {
                Component comp = e.getComponent();
                System.out.println("removed from : " + comp);
        }
       
        public void componentAdded(ContainerEvent e)
        {
                Component comp = e.getComponent();
                System.out.println("added to : " + comp);
        }
}

'Dev > Java' 카테고리의 다른 글

[java reflection] Java Reflection Class 1  (1) 2007.12.16
[ Swing ] JTree 의 Tooltip 구현 변경하기  (1) 2007.12.12
Java Wizard Dialog  (0) 2007.12.08
Posted by yeori
,