문제

다음 접근 방식을 사용하여 EDT 외부로 스윙에서/에서 구성 요소와 반환 값을 만들었습니다. 예를 들어, 다음 방법은 JFrame, 만들기 위해 JPanel 부모에게 추가하십시오 JFrame:

public JPanel threadSafeAddPanel() {

    final JPanel[] jPanel = new JPanel[1];

    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }

    return jPanel[0];
}

로컬 1 길이 배열은 "결과"를 내부에서 전송하는 데 사용됩니다. Runnable, EDT에서 호출됩니다. 글쎄, 그것은 "약간"해킹 된 것처럼 보이므로 내 질문은 다음과 같습니다.

  1. 이게 말이 되요? 다른 사람이 이런 일을하고 있습니까?
  2. 1 길이 배열이 결과를 전송하는 좋은 방법입니까?
  3. 더 쉬운 방법이 있습니까?
도움이 되었습니까?

해결책

  • 로그인하지 않고 예외를 삼키기 : 나쁜!! - 2 시간 동안 버그 사냥을 한 후 그런 식으로 올 때 자신을 미워할 것입니다.
  • 아니요, 배열은 좋은 방법이 아닙니다. 우선, 호출 코드가 EDT 스레드가 실행되기를 기다릴 수있는 쉬운 방법을 제공하지 않습니다. Runnable 결과를 가져 오기 전에
  • 이런 종류의 일에 대해 명시 적으로 설계된 수업이 있습니다. SwingWorker

다른 팁

어떤 상황에서는 그 방법이 의미가있을 수 있지만 대부분의 시간은 쓸모가 없습니다.

그 이유는 EDT에서 항상 실행되는 사용자 조치 (메뉴 항목 또는 버튼 클릭)의 결과로 대부분의 (전부가 아닌 경우) 구성 요소의 생성이 항상 EDT에서 발생하기 때문입니다.

패널을 만들기 전에 수행해야 할 큰 작업이 있고 EDT를 차단하고 싶지 않은 경우 다른 사람이 제안한대로 Swingworker 또는 긴 작업을 지원하는 스윙 프레임 워크를 사용해야합니다 (일반적으로 어쨌든 내부적으로 스윙 워크 사람이지만 반드시는 아닙니다).

당신의 질문 2와 관련하여, 불행히도 당신은 그렇게 할 방법이 많지 않습니다.

  • 당신이했던 것처럼 1 항목 배열을 사용하십시오. 그것은 가장 쉽지만 가장 추악한 솔루션입니다.
  • 거의 동일한 작업을 수행하고 좀 더 많은 작업이 필요하고 더 깨끗한 항목 보유자 클래스 (아래 참조)를 만듭니다.
  • 마지막으로, java.util.concurrent 시설 (미래 및 호출 가능)을 사용하십시오. 그것은 내가 생각하는 가장 깨끗한 일이지만 가장 많은 노력이 필요합니다.

다음은 단순화 된 항목 보유자 클래스입니다.

public class ItemHolder<T> {
    public void set(T item) {...}
    public T get() {...}
    private T item;
}
  1. a) 의미가 있습니다. b) 내가 아는 것이 아닙니다.
  2. 어느 것도 좋습니다.
  3. 외부에서 jpanel을 만듭니다 invokeAndWait 전화

//이 줄은 MarkDown을 Leacease에 추가했습니다

public JPanel threadSafeAddPanel() {
    final JPanel jPanel = new JPanel();
    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                add(jPanel);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }
    return jPanel;
}

현재 스레드가 EDT인지 쉽게 확인한 다음 해당 컨텍스트에서 단순히 올바르게 실행할 수 있습니다. 리턴 값을 얻기 위해 최종 배열을 사용하는 것은 익명의 내부 클래스를 사용해야하는 가장 쉬운 방법입니다.

public JPanel threadSafeAddPanel() throws InterruptedException, 
        InvocationTargetException {
    if (EventQueue.isDispatchThread()) {
        JPanel panel = new JPanel();
        add(panel);

        return panel; 
    } else {
        final JPanel[] jPanel = new JPanel[1];
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });

        return jPanel[0];
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top