Java Swing JButton时间延迟(闪烁) [英] Java Swing JButton Time Delays (Flicker)

查看:438
本文介绍了Java Swing JButton时间延迟(闪烁)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让我的JButton Flicker Red为我创造的这个游戏。所有在这个网站上的解决方案建议使用线程,并使其睡觉或使用计时器,但暂停所有的似乎是在颜色变化之后

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

这里是我的代码:


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

如果我把一个线程放到第3行睡眠,注释掉第4行,在JButton变成红色之前。 (注意板只是一个JButtons的二维数组)

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)

推荐答案

有任何数量的原因为什么会发生这种情况,

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

根据您的描述,听起来您正在尝试从事件分派主题之外更新UI。

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

Swing是一个单线程环境,它也不是线程安全的。基本上这意味着,期望UI的所有交互/改变在EDT的上下文中执行。不遵循这条规则可能导致各种奇怪和奇妙的行为。

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.

最简单的解决方案是使用 javax.swing.Timer ,它允许您安排定期的定时事件,保证在EDT中执行,例如

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

}

请参阅 Swing中的并发如何使用Swing计时器了解更多详情。

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

一个更复杂的解决方案将允许您使用 Thread ,但需要使用 SwingUtilities.invokeLater 更新UI $ c>,这将在EDT上放置一个事件,该事件将执行一个 Runnable 界面,您可以使用它来更新UI。这可能有同步问题,因为您正在呼叫的线程将在实际事件被触发前移动,并可能导致一些脏更新,除非您仔细控制更新过程...

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...

这篇关于Java Swing JButton时间延迟(闪烁)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆