2

I am trying to flash the icon to the user using a GlassPane. I am running a javax.swing.Timer which basically performs this:

for (int i = 0; i < 3; i++) {
    frame.getGlassPane().setVisible(true);
    try {
        Thread.sleep(500);
    } catch (InterruptedException e1) {
       //To change body of catch statement use File | Settings | File Templates.
        e1.printStackTrace();
    }
    frame.getGlassPane().setVisible(false);
}

Unfortunatly, if I sleep the EDT (current thread within the timer), the icon does not show, as in the paintComponent method did not manage to get invoked fully before the thread went to sleep. Therefore, when the next instruction kicks in, the glass pane is hidden, and, as a result, the icon is never shown. Is there a way to achieve what I want using this (similiar) approach?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Bober02
  • 15,034
  • 31
  • 92
  • 178
  • More examples [here](http://stackoverflow.com/a/2234020/230513) and [here](http://stackoverflow.com/a/2124507/230513). – trashgod Aug 15 '12 at 10:39

2 Answers2

5

You could use a javax.swing.Timer

public FlashTimer() {

    javax.swing.Timer flashTimer = new javax.swing.Timer(500, new FlashHandler());
    flashTimer.setCoalesce(true);
    flashTimer.setRepeats(true);
    flashTimer.setInitialDelay(0);

}

public class FlashHandler implements ActionListener {

    private int counter;

    @Override
    public void actionPerformed(ActionEvent ae) {

        countrol.setVisible(counter % 2 == 0);
        counter++;
        if (counter > 3) {

            ((Timer)ae.getSource()).stop();

        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

It should be obvious - use a separate Thread and do the "blinking logic" there but modify the UI in EDT. Here is a simple example (should be enough to understand the idea):

public static void main ( String[] args )
{
    JFrame frame = new JFrame ();

    final JLabel label = new JLabel ( "X" );
    label.setBorder ( BorderFactory.createEmptyBorder ( 90, 90, 90, 90 ) );
    frame.add ( label );

    frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
    frame.pack ();
    frame.setLocationRelativeTo ( null );
    frame.setVisible ( true );

    new Thread ( new Runnable ()
    {
        public void run ()
        {
            for ( int i = 0; i < 15; i++ )
            {
                try
                {
                    setVisible ( false );
                    Thread.sleep ( 500 );
                    setVisible ( true );
                    Thread.sleep ( 500 );
                }
                catch ( InterruptedException e1 )
                {
                    //
                }
            }
        }

        private void setVisible ( final boolean visible )
        {
            SwingUtilities.invokeLater ( new Runnable ()
            {
                public void run ()
                {
                    label.setVisible ( visible );
                }
            } );
        }
    } ).start ();
}
Mikle Garin
  • 10,083
  • 37
  • 59
  • You could simply the process by using a javax.swing.Timer – MadProgrammer Aug 15 '12 at 09:39
  • @MadProgrammer i cannot (in case i use sleep statements) since Timer action body is performed in EDT. That is why i have used separate Thread. Though its easily doable with timer w/o sleep statements, you will just need to invert component visibility with each timer event. Anyway both approaches are possible and are correct... – Mikle Garin Aug 15 '12 at 10:12
  • you don't need sleep with the Timer, let the timer take care of the sleep and just respond to the ActionEvent. – MadProgrammer Aug 15 '12 at 10:15
  • This is a little circuitous, but it appears to be correctly synchronized. `javax.swing.Timer` hides the complexity. – trashgod Aug 15 '12 at 10:42
  • @MadProgrammer thats exactly what i was saying :) – Mikle Garin Aug 15 '12 at 14:15
  • @trashgod heh, good to know that, but anyway - i doubt its a good way to do things :) – Mikle Garin Aug 15 '12 at 14:16