Repaint glass pane before and after a thread does extra processing

138 views Asked by At

I'm attempting to use a glass pane to gray out a frame while a separate thread performs some image processing (img proc). After the img proc thread finishes, the glass pane should go invisible again. I have confirmed that the glass pane is functioning properly, but repainting doesn't occur before the img proc thread (which indeed executes as expected with the wait and notify working as well) is started. Here's what I have:

The GlassPane class:

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

While building the components of the frame:

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

And in the action listener of a button:

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

Where ctrlr.grayOut() and ctrlr.showFull() are just:

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

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

I've read over a lot of this Painting in AWT and Swing and other threads that perform this type of action. It appears to me that I'm doing the same thing as those that are successful...is there something subtle I am missing?

1

There are 1 answers

0
kiheru On BEST ANSWER

This: lock.wait(); blocks the event dispatch thread so that no drawing can happen. I'd use a SwingWorker for the heavy task. That is, putting the image processing to doInBackground() and the stuff you have after the wait in done().

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