Java Swing JButton Time Delays (Flicker)

我们两清 提交于 2020-01-19 01:54:29

问题


I am trying to make my JButton flicker red for this game I am creating. All the solutions on this website suggest using a thread and putting it to sleep or using a timer, however, the pause allays seems to come after the color change

Here is my code:

Color cb = board[Y1][X1].getBackground();
board[Y1][X1].setBackground(Color.RED);
//Pause
board[Y1][X1].setBackground(cb);

If I put a thread and put it to sleep on line 3 and comment out line 4 the pause will come before the JButton is turned red. (Note board is just a 2D array of JButtons)


回答1:


There are any number reasons why this might be occurring and equally, any number of ways it might be fixed.

Based on your description, it sounds like you're trying to update the UI from outside of the Event Dispatching Thread.

Swing is a single thread environment, it's also not thread safe. Basically what this means is, there is an expectation that all interactions/changes to the UI are carried out within the context of the EDT. Failing to following this rule can lead to all sorts of weird and wonderful behaviour.

The simplest solution is to use a javax.swing.Timer, which allows you to schedule regular timed events which are guaranteed to be executed within the EDT, for example

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FlashyButton {

    public static void main(String[] args) {
        new FlashyButton();
    }

    public FlashyButton() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JButton button;
        private Color[] colors = new Color[]{Color.RED, Color.YELLOW};

        public TestPane() {
            button = new JButton("Flash Gorden");
            button.setContentAreaFilled(false);
            button.setBorderPainted(false);
            button.setFocusPainted(false);
            button.setOpaque(true);
            button.setBackground(Color.YELLOW);
            setLayout(new GridBagLayout());
            add(button);

            Timer timer = new Timer(500, new ActionListener() {
                private int counter = 0;
                @Override
                public void actionPerformed(ActionEvent e) {
                    counter++;
                    if (counter % 2 == 0) {
                        button.setBackground(colors[0]);
                    } else {
                        button.setBackground(colors[1]);
                    }
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }
    }

}

Take a look at Concurrency in Swing and How to Use Swing Timers for more details.

A more complex solution would allow you to use a Thread, but would require to update the UI by using SwingUtilities.invokeLater, which would place an event onto the EDT that would execute a Runnable interface, which you would use to update the UI. This could have synchronisation issues as the Thread you're calling from will have moved on before the actual event is triggered and could cause some dirty updates, unless you control the update process carefully...



来源:https://stackoverflow.com/questions/23820488/java-swing-jbutton-time-delays-flicker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!