Java Swing重绘延迟

时间:2014-06-24 18:50:00

标签: java multithreading swing delay

我正在编写一个使用Wolfram Alpha Java Bindings的私有应用程序。应用程序的GUI使用Swing实现。我的Wolfram Alpha插件有一个如下功能:

public void fire(String value) {

    // This sets the field state to loading
    _state = loading;

    // This tells the controller to redraw the window
    // When reading the state of the plugin it sets an
    // animated gif at a JPanel. This should be displayed
    // before the application is blocked by the Wolfram Alpha
    // Request. 

    // updateInput does nothing more then call repaint after some
    // other function calls. No special threading included. 

    getController().updateInput("");


    // My wolfram request follows:

    WAQuery query = _engine.createQuery();
    query.setInput(value);
    try {
        // For educational purposes, print out the URL we are about to send:
        System.out.println("Query URL:");
        System.out.println(_engine.toURL(query));
        System.out.println("");

        // This sends the URL to the Wolfram|Alpha server, gets the XML result
        // and parses it into an object hierarchy held by the WAQueryResult object.
        WAQueryResult queryResult = _engine.performQuery(query);

        if (queryResult.isError()) {
            System.out.println("Query error");
            System.out.println("  error code: " + queryResult.getErrorCode());
            System.out.println("  error message: " + queryResult.getErrorMessage());
        } else if (!queryResult.isSuccess()) {
            System.out.println("Query was not understood; no results available.");
        } else {
            // Got a result.
            System.out.println("Successful query. Pods follow:\n");
            for (WAPod pod : queryResult.getPods()) {
                if (!pod.isError()) {
                    System.out.println(pod.getTitle());
                    System.out.println("------------");
                    for (WASubpod subpod : pod.getSubpods()) {
                        for (Object element : subpod.getContents()) {
                            if (element instanceof WAPlainText) {
                                System.out.println(((WAPlainText) element).getText());
                                System.out.println("");
                            }
                        }
                    }
                    System.out.println("");
                }
            }
            // We ignored many other types of Wolfram|Alpha output, such as warnings, assumptions, etc.
            // These can be obtained by methods of WAQueryResult or objects deeper in the hierarchy.
        }
    } catch (WAException e) {
        e.printStackTrace();
    }


}

问题是在重新绘制窗口之前启动了请求。我的请求延迟大约一秒钟,然后显示加载动画。应在启动请求之前显示此动画。

到目前为止我尝试了什么:

  • Wolfram查询前面的Thread.sleep()。但那会阻止重画吗?! - 同样不受欢迎的行为
  • 将请求置于可运行的 - 同样不需要的行为
  • 将请求放入由Thread扩展的类中 - 同样不需要的行为
  • 将两者结合使用Thread.sleep() - 同样不需要的行为

我在这里监督什么?

2 个答案:

答案 0 :(得分:2)

  

我的请求延迟大约一秒钟,然后显示加载动画。应在启动请求之前显示此动画。

永远不要在Swing应用程序中使用Thread.sleep(),有时会挂起您在帖子中已经说明的整个应用程序。在这种情况下你应该使用Swing Timer

请查看How to Use Swing Timers

示例代码:

Timer timer = new Timer(1000, new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent arg0) {            
        // start loading animation now
    }
});
timer.setRepeats(false);
timer.start()

答案 1 :(得分:2)

我的建议是:

  • 使用背景线程,特别是SwingWorker'
  • 使用SwingWorker的doInBackground方法执行长时间运行的代码。
  • 在执行SwingWorker之前启动动画显示。
  • 为SwingWorker提供一个PropertyChangeListener,当SwingWorker的状态完成后,停止动画。
  • 确保动画不会占用Swing事件线程。使用Swing Timer。

例如,

  // start animation -- be sure to use a Swing Timer or
  // other way to prevent tying up the Swing event thread

  SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() {
     protected Void doInBackground() throws Exception {
        fire(someValue);
        return null;
     };
  };
  myWorker.addPropertyChangeListener(new PropertyChangeListener() {

     @Override
     public void propertyChange(PropertyChangeEvent pcEvt) {
        if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
           // .... stop the animation here
        }
     }
  });

  myWorker.execute();