2010-12-06 4 views
15

Java 응용 프로그램에서 주 모듈이 호출 될 때 별도의 스레드에서 SWT GUI가 시작됩니다. 메인 스레드에서 긴 오퍼레이션을 수행하고 GUI 스레드를 업데이트해야합니다. 주 스레드에서 GUI 스레드를 업데이트하려고하면 레이블 텍스트 나 다른 것을 변경하면 java.lang.NullPointerException이됩니다. SWT가 비 UI 스레드가 UI 개체를 업데이트 할 수 없기 때문에 온라인에서 읽은 것입니다. 어떻게 메인 스레드에서 GUI 스레드를 업데이트 할 수 있습니다.다른 스레드에서 SWT 개체 업데이트

나는 온라인에서 몇 가지 예제를 찾았지만 GUI는 메인 스레드에서 실행되고 긴 조작은 별도의 스레드에있는 시나리오를 다룹니다. 내 시나리오는 그 반대 다.

GUI 스레드에서 위젯을 어떻게 업데이트 할 수 있습니까?

+0

일반적으로 잘못된 스레드에서 일부 GUI 구성 요소를 업데이트 할 때'NullPointerException'을 얻지 못합니다. 정말 스레딩 문제일까요? – Flavio

답변

7

GUI 구성 요소가 생성되기 전에 액세스하려고하기 때문에 java.lang.NullPointerException이 발생한다고 생각합니다. 이상적으로는

내가이

package test; 


import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Label; 
import org.eclipse.swt.widgets.Shell; 

public class GUIThread implements Runnable 
{ 
    private Display display; 
    private Label label; 
    public Display getDisplay(){ 
     return display; 
    } 
    public void run() 
    { 
     display = new Display(); 
     Shell shell = new Shell(display); 
     shell.setLayout(new GridLayout()); 
     shell.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,false)); 
     label = new Label(shell,SWT.NONE); 
     label.setText(" -- "); 
     shell.open(); 
     shell.pack(); 

     while (!shell.isDisposed()) { 
     if (!display.readAndDispatch()) display.sleep(); 
     } 
     display.dispose(); 
    } 

    public synchronized void update(final int value) 
    { 
     if (display == null || display.isDisposed()) 
      return; 
     display.asyncExec(new Runnable() { 

      public void run() { 
       label.setText(""+value); 
      } 
     }); 

    } 

} 

처럼 그리고 내 주요 방법 ... 별도의 스레드에서 하나의 GUI를 만들 ... 예를 들어 ... 창조 얻을 수있는 GUI 구성 요소에 대한 기다려야 전 우리는 위의 코드에 POINT OF FOCUS을 주석 경우 지금 ....

package test; 

import org.eclipse.swt.widgets.Display; 

public class Main 
{ 

    public static void main(String[] args) throws Exception 
    { 
     final GUIThread gui = new GUIThread(); 
     Thread t = new Thread(gui); 
     t.start(); 

     Thread.sleep(3000); // POINT OF FOCUS 
     Display d = gui.getDisplay(); 

     for(int i = 0; i<100; i++) 
     {   
      System.out.println(i + " " + d); 
      gui.update(i); 
      Thread.sleep(500); 
     } 
    } 
} 

을 같은 것을 할 나는 항상 NullPointerException을 얻을 것이다 ...하지만 삼초의 지연은 내 GUI 스레드에게 될 수있는 충분한 시간을 제공합니다 준비 상태이므로를 통과하지 못합니다......

이와 같은 시나리오에서는 waityield 메서드를 효율적으로 사용해야합니다. 그렇지 않으면 "버그 찾기 어려움"이 발생합니다. 즉, UI가 제대로 인스턴스화 될 때까지 기다린 다음 yield ...

또한 실제 처리는 메인 스레드에서 이루어지며 GUI는 별도의 스레드에서 실행 중입니다 ... 적절하게 통신하려면 일부 공유 및 동기화 된 데이터 구조가 있어야합니다. 또는 다음을 사용하여 수행 할 수 있습니다. 소켓 통신 ... 일부 port 및 GUI 스레드 asynchronously 해당 포트에서 수신 대기 메인 스레드 ....

희망이 throug 것입니다 당신의 문제에 대한 약간의 조명 ....

+0

안녕하세요 Favonius.NullPointerException은 당신이 말한 것과 정확히 일치합니다. 당신은 GUI를 업데이트하고 그 오류를 제거하는 두 가지 문제를 해결하는 데 도움이 답변했습니다. 감사. –

32

짧게 말하면 SWT는 단일 스레드 UI 툴킷입니다. 따라서 SWT 이벤트 스레드에서 위젯을 업데이트해야합니다 (예 : 스윙). 따라서, 익명 Runnable 클래스를 사용하여 새로 고침을 호출해야합니다 : 더 긴 설명은

Display.getDefault().asyncExec(new Runnable() { 
    public void run() { 
     someSwtLabel.setText("Complete!"); 
    } 
}); 

을,이 JavaLobby 문서에서는이 스레딩 사용 모델에 좋은 소개합니다.

+2

필요한 경우 syncExec을 사용하여 동기식 업데이트를 얻을 수도 있습니다. 그러나 나는 또한 당신의 문제가 다르다는 것을 다른 사람들과 함께한다. 당신은 널 참조에 접근하고있다. 비 -Ui 스레드 (잘못된 스레드 액세스 또는 이와 유사한 것)에서 일부 SWT 메서드를 호출 할 때 다른 예외가 발생합니다. – duduamar

+1

JNI 호출 API를 사용하여 UI를 업데이트하려는 경우 모든 트릭이 네이티브 스레드에서 호출됩니다. ? 백업 스레드가 자바 메소드를 호출하지 않더라도 잠긴 UI 만 있습니다. (a) syncExec를 시도해도 효과는 동일하게 유지됩니다. 잠금 UI ... – kneo

관련 문제