Java Swing - 闪烁图标未显示



我正在尝试使用GlassPane将图标闪烁给用户。我正在运行一个基本上执行此操作的javax.swing.Timer

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

不幸的是,如果我使EDT(计时器中的当前线程)休眠,则图标不会显示,因为在paintComponent方法中,在线程进入睡眠状态之前无法完全调用。因此,当下一条指令启动时,玻璃窗格将被隐藏,因此,图标永远不会显示。有没有办法使用这种(类似)方法实现我想要的?

您可以使用

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

这应该是显而易见的 - 使用单独的线程并在那里执行"闪烁逻辑",但在 EDT 中修改 UI。这里有一个简单的例子(应该足以理解这个想法):

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

最新更新