SWT: Periodically update GUI

三世轮回 提交于 2019-12-25 02:08:07

问题


I have an SWT GUI which displays a list taken from a database. What I would like for it to do is to periodically update the GUI, which would involve clearing everything in the shell and running the populateList() method again. I have tried several suggested strategies for this, but the GUI never updates. My latest attempt is using display.asyncexec to create a thread to handle this. This appears to give me an invalid thread access error.

Here's my code:

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;

    }




}

回答1:


As Liam15 has already mentioned, you should start a different thread. Otherwise you will block the UI and it will become unresponsive. The thread should handle the data acquisition and then update the UI synchronously or asynchronously.

Here is an example how your open() method could look like:

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

In order to clear the shell and update the shell contents, you can add the following lines of code to your populateList() method.

At the beginning of the method add:

Control[] oldControls = shell.getChildren();

At the end of the method add:

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



回答2:


Use below method on Display

 public void timerExec (int milliseconds, Runnable runnable)

execute it before you run event loop.

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

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



回答3:


You could run a separate thread with a loop that periodically re-opens the GUI or just updates some information.



来源:https://stackoverflow.com/questions/15710992/swt-periodically-update-gui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!