只有在阻塞方法完成后才会出现LayerUI

时间:2014-06-07 08:25:58

标签: java multithreading paint

我使用LayerUI的自定义子类创建了一些加载的指示。

列表是StringWorker子类的 arraylist 。它的 get 方法是一个阻塞调用,所以我认为这个问题只是不知道如何修复它。该层启动一个计时器,据我所知,计时器在他们自己的线程中执行,因此阻止 get 不应该是干涉。

        loadingLayer.setVisible(true);
        lockComponents();
        for(int i = 0; i < list.size(); i++) {
            try {
                System.out.println("About to check "+i);
                if(list.get(i).get() == null) {

                }
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            } catch (ExecutionException e1) {
                e1.printStackTrace();
            }
        }
        unlockComponents();
        loadingLayer.setVisible(false);

只有在完成所有这些代码后才会出现“loadingLayer”。

LoadingLayerUI类:

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.plaf.LayerUI;
public class LoadingLayerUI extends LayerUI<JComponent> implements ActionListener {

/**
 * 
 */
private static final long serialVersionUID = 827885062549399916L;
private boolean isShowing;
private Timer timer;


private String text;


@Override
public void paint(Graphics g, JComponent jc) {
    super.paint(g, jc);
    if(!isShowing) 
        return;

    Graphics2D g2 = (Graphics2D) g.create();

    int w = jc.getWidth();
    int h = jc.getHeight();
    g2.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, .7f));
    g2.setPaint(Color.LIGHT_GRAY);
    g2.fillRect(0, 0, w, h);

    g2.setColor(Color.BLACK);
    Font font = new Font("Sans-Serif",Font.BOLD, 20);
    int width = g2.getFontMetrics(font).stringWidth("Loading");
    g2.setFont(font);
    if(text != null) 
        g2.drawString(text, (w-width)/2, h/2);

    g2.dispose();
    jc.repaint();
}

public void setVisible(boolean set) {
    this.isShowing = set;
    if(isShowing) {
        timer = new Timer(200, this);
        timer.start();
    }
    else {
        timer.stop();
    }
}


@Override
public void actionPerformed(ActionEvent e) {
    if(!isShowing && timer.isRunning())
        timer.stop();

    if(text == null || text.equals("Downloading...")) {
        text = "Downloading";
    }
    else 
        text += ".";

}
}

2 个答案:

答案 0 :(得分:1)

当你使用Swing时,你应该在一个单独的线程中完成长时间运行的任务。

以下是教程:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

答案 1 :(得分:1)

我将使用阻塞方法 get 的代码移动到一个单独的线程,并在完成后调用方法。现在它似乎工作。当需要时,图层会出现并消失。

        loadingLayer.setVisible(true);
        new Thread(new Runnable() {
            public void run() {
                for(int i = 0; i < list.size(); i++) {
                    try {
                        if(list.get(i).get() == null) {

                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    } catch (ExecutionException e1) {
                        e1.printStackTrace();
                    }
                }
                downloadComplete();
            }
        }).start();

downloadComplete 方法只是隐藏图层。