2013-03-29 3 views
0

데이터베이스에서 가져온 목록을 표시하는 SWT GUI가 있습니다. 내가하고 싶은 것은 쉘에서 모든 것을 지우고 populateList() 메소드를 다시 실행하는 것과 관련된 GUI를 주기적으로 업데이트하는 것이다. 나는 이것을 위해 몇 가지 제안 된 전략을 시도했지만 GUI는 결코 업데이트되지 않습니다. 최근의 시도는 display.asyncexec을 사용하여이 문제를 처리하는 스레드를 만드는 것입니다. 이 메시지는 잘못된 스레드 액세스 오류를 나타냅니다.SWT : 정기적으로 GUI 업데이트

package display; 
import java.io.IOException; 
import java.io.StringReader; 
import java.util.ArrayList; 
import java.util.Timer; 
import java.util.TimerTask; 

import object_models.Request; 
import util.RestClient.RequestMethod; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.graphics.Color; 
import org.eclipse.swt.graphics.Font; 
import org.eclipse.swt.graphics.Image; 
import org.eclipse.swt.graphics.Point; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.layout.RowData; 
import org.eclipse.swt.layout.RowLayout; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Control; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Label; 
import org.eclipse.swt.widgets.Shell; 
import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlPullParserException; 
import org.xmlpull.v1.XmlPullParserFactory; 


import util.RestClient; 


public class StoragePickupDisplay { 

    protected Shell shell; 


    private ArrayList<Request> pendingRequests; 
    /** 
    * Launch the application. 
    * @param args 
    */ 
    public static void main(String[] args) { 
     try { 
      StoragePickupDisplay window = new StoragePickupDisplay(); 
      window.open(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Open the window. 
    * @throws InterruptedException 
    */ 
    public void open() throws InterruptedException { 
     Display display = Display.getDefault(); 
     createContents(); 
     populateList(); 
     shell.open(); 
     shell.layout(); 

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



     display.asyncExec(new Runnable() { 
      public void run() { 
       populateList(); 
      } 
      }); 
     Thread.sleep(1000); 

     } 
    } 

    /** 
    * Create contents of the window. 
    */ 
    protected void createContents() { 
     shell = new Shell(); 
     //shell.setMaximized(true); 

     //shell.setFullScreen(true); 
     shell.setText("Request Pickup"); 
     shell.setMaximized(true); 


     GridLayout gridLayout= new GridLayout(1,false); 

     shell.setLayout(gridLayout); 




    } 
    protected void populateList(){ 


     pendingRequests=new ArrayList<Request>(); 

     RestClient client = new RestClient("http://XXXXXX:8080/StorageWebService/rest/operations/getPendingRequests"); 

     try { 
      client.Execute(RequestMethod.GET); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     String response = client.getResponse(); 


     pendingRequests= parseResponse(response); 



     for(Request request: pendingRequests){ 
      Composite row = new Composite(shell,SWT.NONE); 

      GridLayout gridLayout = new GridLayout(4,true); 
      gridLayout.marginTop=5; 
      row.setLayout(gridLayout); 
      row.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); 


      Composite left = new Composite(row,SWT.NONE); 
      left.setLayout(new GridLayout(2,false)); 
      left.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); 

      Label label = new Label(left,SWT.LEFT); 
      label.setText(""+request.getId()); 

      label.setFont(new Font(Display.getDefault(),"Arial",30, SWT.NONE)); 
      label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false)); 


      label = new Label(left,SWT.LEFT); 
      label.setText(request.getNickname()); 
      label.setFont(new Font(Display.getDefault(),"Arial",30, SWT.NONE)); 
      label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); 

      label = new Label(row,SWT.LEFT); 
      label.setText(""+request.getNumberCompleted()+" of "+request.getNumberItems()+" Picked"); 
      label.setFont(new Font(Display.getDefault(),"Arial",30, SWT.NONE)); 
      label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); 

      label = new Label(row,SWT.LEFT); 
      label.setText("Estimated Wait Time:"); 
      label.setFont(new Font(Display.getDefault(),"Arial",30, SWT.NONE)); 
      label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); 



      Label separator = new Label(shell, SWT.HORIZONTAL|SWT.SEPARATOR|SWT.PUSH); 

      GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false); 
      //gridData.horizontalSpan=4; 
      separator.setLayoutData(gridData); 



     } 

    } 
    public ArrayList<Request> parseResponse(String response){ 
     ArrayList<Request> list = new ArrayList<Request>(); 
     try { 



      XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); 
      parser.setInput(new StringReader(response)); 

      int eventType = parser.getEventType(); 


      Request curRequest = new Request(); 


      while (eventType != XmlPullParser.END_DOCUMENT) { 
       if (eventType == XmlPullParser.START_TAG) { 
        String name = parser.getName(); 
        if (name.equalsIgnoreCase("id")) { 
         String text = parser.nextText(); 
         curRequest.setId(Integer.parseInt(text)); 

        } 
        if (name.equalsIgnoreCase("nickname")) { 
         String text = parser.nextText(); 
         curRequest.setNickname(text); 

        } 
        if (name.equalsIgnoreCase("numberCompleted")) { 
         String text = parser.nextText(); 
         curRequest.setNumberCompleted(Integer.parseInt(text)); 

        } 
        if (name.equalsIgnoreCase("numberItems")) { 
         String text = parser.nextText(); 
         curRequest.setNumberItems(Integer.parseInt(text)); 

        } 
        if (name.equalsIgnoreCase("status")) { 
         String text = parser.nextText(); 
         curRequest.setStatus(Integer.parseInt(text)); 

        } 

       } 

       if (eventType == XmlPullParser.END_TAG) { 
        if (parser.getName().equalsIgnoreCase("Request")) { 
         list.add(curRequest); 
         curRequest = new Request(); 
        } 
       } 
       eventType = parser.next(); 
      } 

     } catch (XmlPullParserException e) { 

      e.printStackTrace(); 
     } catch (IOException e) { 

      e.printStackTrace(); 
     } 

     return list; 

    } 




} 
+0

Stackoverflow 검색 : 업데이트 GUI 스레드 \ [java \]]는 1,131 개의 결과를 제공합니다. 정기적 인 업데이트를 위해 하나 더 필요합니까? 주기적인 업데이트에 대한 구체적인 내용은 무엇입니까? 한 번 업데이트 할 수 있으면 정기적으로 업데이트 할 수 있습니다. 권리? 이 사용자는 GUI를 전혀 업데이트 할 수 없다고 알려줍니다. 그것은 주기적으로도 그를 위해 부적절한 것 같습니다. 주기성은 GUI와 관련이 없습니다. – Val

+2

@Val : Stack Overflow는 더 이상 질문과 대답 사이트가 아닙니다. 헬프 데스크입니다. 아무리 많은 질문을 던지더라도 누군가는 그 평판 포인트를 얻기위한 답을 얻습니다. –

+0

@ GilbertLeBlanc 그러나 우리는 여전히 질문에 대해 하향 조정할 수 있습니다. 나는 너의 downvote을 보지 않는다. 포기 했니? – Val

답변

3

Liam15가 이미 언급 했으므로 다른 스레드를 시작해야합니다. 그렇지 않으면 UI가 차단되어 응답하지 않게됩니다. 스레드는 데이터 획득을 처리 한 다음 동기 또는 비동기 적으로 UI를 업데이트해야합니다. 여기

는 open() 메서드의 모습 수있는 방법을 예입니다

, 당신이 당신의 populateList 다음 코드 줄을 추가 할 수 있습니다 쉘을 지우고 쉘 내용을 업데이트하기 위해
public void open() throws InterruptedException { 
    Display display = Display.getDefault(); 
    createContents(); 
    shell.open(); 

    Thread updateThread = new Thread() { 
     public void run() { 
      while (true) { 
       final ArrayList<Request> pendingRequests = getPendingRequests(); 
       Display.getDefault().syncExec(new Runnable() { 

        @Override 
        public void run() { 
         populateList(pendingRequests); 
        } 
       }); 

       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    }; 
    // background thread 
    updateThread.setDaemon(true); 
    updateThread.start(); 

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

() 방법. 방법의 시작 부분에서

추가 :

Control[] oldControls = shell.getChildren(); 

방법의 추가의 말 : 방법 아래

for (Control oldControl : oldControls) { 
    oldControl.dispose(); 
} 
shell.layout(); 
+0

감사합니다. 내가 필요한 것! –

0

당신은 주기적으로 루프와 별도의 스레드를 실행 할 수있는 GUI를 다시는-열거 나 그냥 몇 가지 정보를 업데이트 :

여기 내 코드입니다.

1

사용 Display

public void timerExec (int milliseconds, Runnable runnable) 

에 전에 그것을 실행 이벤트 루프를 실행하십시오.

ex: 
display.timerExec(30000, new Runnable() { 
      public void run() { 
       populateList(); 
      } 
      }); 

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

GUI를 업데이트하려면 무엇인가해야합니까? populateList 메소드는 레이블을 더 추가해야하지만 표시되지 않습니다. –

+0

또한이 작업은 한 번만 실행됩니다. 나는 그것이 반복적으로 일어날 필요가있다. –

+0

아, 그 shell.layout() 내가 필요한 것을 볼 수 있습니다. –

관련 문제