0

我有一个 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;

    }




}
4

3 回答 3

3

正如 Liam15 已经提到的,您应该启动一个不同的线程。否则,您将阻止 UI,它会变得无响应。线程应处理数据获取,然后同步或异步更新 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();
于 2013-03-31T10:26:29.487 回答
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();
            }
于 2013-04-01T14:30:20.160 回答
0

您可以运行一个带有循环的单独线程,该循环定期重新打开 GUI 或仅更新一些信息。

于 2013-03-29T20:48:15.757 回答