2010-01-29 2 views
8

스윙 응용 프로그램에서 하나의 서브 패널을 가지고 있으며 각각 JSlider을 수신합니다. 주변의 부모 패널은 모든 하위 패널도 수신합니다. 아래 예제에서 일관된 결과를 얻으려면 부모를 먼저 추가하고 , 로컬 수신기를 추가해야했습니다. 이는 EventListenerList에 명시된 주문과 article에 설명 된대로 이해가됩니다. 그 명령에 의지 할 수 있습니까? 아니면 다른 이벤트를 보내야합니까?EventListenerList 발생 순서

class SubPanel extends JPanel implements ChangeListener { 

    private final JSlider slider = new JSlider(); 
    private final JLabel label = new JLabel(); 
    private final String name; 
    private float value; 

    public SubPanel(String name, float value, ChangeListener parent) { 
     this.name = name; 
     this.value = value; 
     ... 
     slider.addChangeListener(parent); 
     slider.addChangeListener(this); 
    } 
    ... 
} 

부록은 : EventListenerList의 논의는 구현 조언보다는 보장 것으로 보인다. pstanton에 의해 제안 된 연결 방식은 정확한 순서를보다 확실하게 시행합니다. 예를 들어, SubPanelChangeListener은 단순히 이벤트를 상위로 전달할 수 있습니다. JSlider에와 JComponent의 등의 문서가 청취자 통지의 순서를 언급하지 않기 때문에

@Override 
    public void stateChanged(ChangeEvent e) { 
     ... 
     parent.stateChanged(e); 
    } 
+0

흥미로운 질문과 답변! 1+ –

+0

['Converter'] (http://docs.oracle.com/javase/tutorial/uiswing/components/panel.html) 응용 프로그램에는'ConverterRangeModel'의 예제가 포함되어 있습니다. – trashgod

+0

'googling'하는 동안 나는 방금 게시물을 얻었고, 자세히 설명하고 싶었다. 게시물 개수를 확인해 주시고 제가 설명한 바가 잘못 될 수 있다면 저를 지적하십시오! – Sage

답변

4

, 나는 적어도 JRE의 각 후속 버전에 대한 철저한 테스트하지 않고, 그것에 의존 주저 것입니다.

당신이 정말로, 순서에 의존하는 등 청취자 두 가지를 알려 드리겠습니다 청취자의 사슬, 즉 리스너를 설정 고려해야 할 경우

+0

일반적으로 상태 변경 (입력과 반대) 이벤트는 이벤트 객체를 완전히 무시하기에 더 강력합니다. (성능에 대해 혼동하지 마세요. 평균 CPU가 밀리 초 단위로 할 수있는 * 수백만 * *와 비교하여 얼마나 많은 사이클을 사용하는지 생각하십시오.) –

+0

@ 톰 : 내 대답이나 그 질문에 대한 의견입니까? – pstanton

+0

좋습니다. 요점은 명확하지 않습니다. – pstanton

1

약간 오래된 답변을 매우 늦게. 그러나 내 불안정한 마음으로 인해 나를 강타하고있다.

해당 주문을 사용하거나 다른 이벤트를 보내야합니까?

나는 그들이 순서를 유지하는 것이 믿는다, 구성 요소의 설명서는 많이 말해주지 않지만, 소스 코드는 항상 우리의 친구입니다. 우리가 addChangeListener(listener) 기능에서 JSlider의 시작하자 :

1 단계 : 호출 jSlider.addChangeListener(listener)listener listlistener을 추가합니다.

public void addChangeListener(ChangeListener l) { 
     listenerList.add(ChangeListener.class, l); 
    } 

단계 2 : synchronized add(Class<T> t, T l) : EvenListenerList 소스 코드 Object[i]이고, 청취자와 새로운 청취자가 Object[]의 끝과 인덱스 i 첨가되도록 해당 유형을 추가 청자의 유형 및 Object[i+1]은 리스너 인스턴스입니다.

public synchronized <T extends EventListener> void add(Class<T> t, T l) { 
    // There were other checking here 
    // omitted as irrelevant to the discussion 
    } else { 
     // Otherwise copy the array and add the new listener 
     int i = listenerList.length; 
     Object[] tmp = new Object[i+2]; 
     System.arraycopy(listenerList, 0, tmp, 0, i); 

     tmp[i] = t; // add the class type 
     tmp[i+1] = l; // add the listener instance 

     listenerList = tmp; 
    } 
    } 

3 단계 :JSliderfireStateChanged() 기능은 목록의 모든 리스너에 이벤트를 전달하기위한 책임이 있습니다. 소스 코드는 청취자 목록의 끝에서 각 청취자의 stateChanged() 함수를 호출하여 각 청취자를 호출한다고 알려줍니다.

protected void fireStateChanged() { 
     Object[] listeners = listenerList.getListenerList(); 
     for (int i = listeners.length - 2; i >= 0; i -= 2) { 
      if (listeners[i]==ChangeListener.class) { 
       if (changeEvent == null) { 
        changeEvent = new ChangeEvent(this); 
       } 
       ((ChangeListener)listeners[i+1]).stateChanged(changeEvent); 
      } 
     } 
    } 

여름 :의 메커니즘 (동기화)를 추가하고 청취자리스트에 청취자의 방문은 우리에게 그것을 알려줍니다 : 그것은 마지막 FIRST 방문 추가 주문 유지한다. 즉, 나중에 (자식) 추가 된 리스너가 먼저 호출 된 다음 이전 (부모)이 추가 된 리스너 등이 호출됩니다.스윙 이벤트 처리 코드는 EDT에서 실행됩니다. EventQueue은 이벤트를 enqueued과 같은 순서로 전달하므로 부모 이벤트 이전에 하위 이벤트가 전달됩니다.

나는 이 유지되고 있다고 생각합니다.

+1

흥미로운 디자인 패턴이지만 구현에 대한 자세한 설명은 내가 의존하기를 꺼려합니다. 통지의 순서가 명시 적으로 지정되지 않은 (콩 사양 f.i. 참조) 단지 @의 trashgod의 의견을 강조하기위한) – trashgod

+0

아마,하지만 내게는'EventListListener' 메커니즘을 호출. 또한, 관측 대상의 수명 기간 동안 순서가 바뀔 수 있습니다 (f.i. LAF 변경시 리스너를 제거/추가합니다. 그래서, **는 ** 어떤 구체적인 구현에 의존하지 않는 일반적으로, 그것은 예고없이 변경 될 수 있습니다! – Sage

+1

을 * :) 우리가 꾸지람하는 것 같다 * 신뢰할 수없는 – kleopatra