SWT:定期更新GUI

时间:2013-03-29 20:33:25

标签: java multithreading user-interface swt

我有一个SWT GUI,显示从数据库中获取的列表。我想要它做的是定期更新GUI,这将涉及清除shell中的所有内容并再次运行populateList()方法。我已经尝试了几种建议的策略,但GUI永远不会更新。我最近的尝试是使用display.asyncexec创建一个线程来处理这个问题。这似乎给我一个无效的线程访问错误。

这是我的代码:

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;

    }




}

3 个答案:

答案 0 :(得分:3)

正如Liam15已经提到的,你应该开始一个不同的线程。否则你将阻止用户界面,它将无法响应。线程应处理数据采集,然后同步或异步更新UI。

以下是open()方法的示例:

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();
        }
    }
}

为了清除shell并更新shell内容,可以在populateList()方法中添加以下代码行。

在方法的开头添加:

Control[] oldControls = shell.getChildren();

在方法结束时添加:

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

答案 1 :(得分: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();
            }

答案 2 :(得分:0)

您可以使用循环运行单独的线程,该循环会定期重新打开GUI或仅更新某些信息。