在线程执行额外处理之前和之后重新绘制玻璃窗格

时间:2013-08-07 14:55:50

标签: java multithreading swing paintcomponent glasspane

我正在尝试使用玻璃窗格使框架变灰,而单独的线程执行某些图像处理(img proc)。 img proc线程完成后,玻璃窗格应该再次隐形。我已经确认玻璃窗格运行正常,但是在img proc线程(确实按照预期执行,等待并通知工作)开始之前不会重新绘制。这就是我所拥有的:

GlassPane类:

class GlassPane extends JComponent implements MouseListener
{
    GlassPane()
    {
        super();
        setLayout(new BorderLayout());
        setOpaque(false); // So that Color's alpha channel is used
        addMouseListener(this);
    }
    @Override
    protected void paintComponent(Graphics g)
    {
        Rectangle bounds = g.getClipBounds();

        g.setColor(new Color(255,255,255,160));

        g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
    }
...
}

构建框架的组件时:

gPane = new GlassPane();
rootFrame.setGlassPane(gPane);
setGlassPane( false );
...
public void setGlassPane( boolean gray )
{
    if( gray )
        keyCatcher.disable();
    else
        keyCatcher.enable();

    gPane.setVisible(gray);
    gPane.repaint(); // Also tried gPane.repaint(0);
    gPane.invalidate();
}

在按钮的动作监听器中:

...
System.out.println( "Answer button pressed..." );
    ctrlr.grayOut();

    new Thread( new Runnable()
    { 
        public void run(){
            int responses[];
            ImgProc ip = new ImgProc(ctrlr);
            ArrayList<ColorModel> model = ctrlr.getColorModel();
            responses = ip.findResponses( camContent.getCrntImage(), model, (source == ansAndDisplayBtn) );
            ctrlr.setResponses(responses);
            synchronized(lock)
            {
                lock.notifyAll();
                System.out.println( "Notified..." );
            }
        }
    }).start();

    synchronized(lock)
    {
        try {
            System.out.println( "Waiting..." );
            lock.wait();
            System.out.println( "Responses retreived..." );
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        qContent.answer();
        qContent.updateResponses();

        if( scrnMode )
        {
            proj_qContent.answer();
            proj_qContent.updateResponses();
        }
    }
    ctrlr.showFull();
    ...

ctrlr.grayOut()ctrlr.showFull()只是:

public void grayOut()
{
    ((MainUI) mainUI).setGlassPane(true);
}

public void showFull()
{
    ((MainUI) mainUI).setGlassPane(false);
}

我已经阅读了很多这种Painting in AWT and Swing以及执行此类操作的其他线程。在我看来,我做的事与那些成功的事情一样......我有什么微妙的缺失吗?

1 个答案:

答案 0 :(得分:1)

这:lock.wait();阻止事件调度线程,以便不会发生绘图。我会用SwingWorker来完成繁重的任务。也就是说,将图像处理设置为doInBackground()以及waitdone()之后的内容。

// Inform the user the task is running
ctrlr.grayOut();

new SwingWorker<Void, Void>() {
   @Override
   public Void doInBackground() {
       // process the image
       ...
       return null;
   }

   @Override
   protected void done() {
        // Everything done, inform the user
        ...
        ctrlr.showFull();
    }
}.execute();