Jbutton在两种背景颜色之间闪烁 [英] Jbutton flash between two background colors

查看:110
本文介绍了Jbutton在两种背景颜色之间闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题:该程序在我的情况下延迟的有效方法。

My problem: Efficient way for the program to delay in my scenario.

我的情况:
我正在为一个简短的项目(长话短说)制作问答游戏。当用户按下上面有答案的四个Jbutton之一时,就会回答问题。然后,我的quizengine类调用此处显示的paintbutton方法。之后,它将继续调用负责使下一个问题出现的其他方法。现在,我想要的是使按钮在两种颜色之间随时间间隔的减少而变化。

My Scenario: I am making a quiz game for a short project, long story short. A question is answered when the user presses one of four Jbuttons having an answer on them. Then my quizengine class calls the paintbutton method showed here. After that it proceeds to call some other methods responsible for making the next question appear. Now what I want is to make the button change between two colors with decreasing time intervals.

到目前为止我已经尝试了什么:
首先,我在paintbutton方法和将接口更改为以下方法之间放置了一个JoptionPane。下一个问题只是看按钮是否会改变颜色。它确实成功了。当然,这不是我的意图,我只想要一个时间间隔。
然后我尝试使用Thread.Sleep。尽管程序会在更改到下一个问题之前等待,但是颜色更改是不可见的。
最后,我尝试了Timer Thingy的实现(可能不正确),尽管它改变了颜色,但程序仍继续进行并继续下一个问题。

What have I tried so far: First I placed a JoptionPane between the paintbutton method and the method that changes the interface to the next question just to see if the button would change color. It did successfully. Of course that wasn't my intention, I wanted just a time interval. Then I tried using Thread.Sleep. Although the program would wait before changing to the next question, the color change was not visible. Finally I tried an implementation of the Timer thingy (probably not correctly) which although it changed the color the program went ahead and proceeded to the next question.

我想成为代码

  /* Paints the button pressed red or green
   *  Green if the anwser is correct red if 
   *  its false
   *
   * @param int bnr the number of the button
   * @param boolean corr true if correct false if false :D
   */
   public static void paintbutton(int bnr,boolean corr) { 
       for (int i=10;i>1;i--){
        b[bnr-1].setBackground(null);     
        //wait for i*100 milliseconds
        b[bnr-1].setBackground(corr?Color.green:Color.red);          
       }
   }


推荐答案

从一些基础知识开始。 Swing是单线程的,这意味着您绝不能在Event Dispatching Thread的上下文中阻塞或执行长时间运行的代码,这将使UI冻结并且用户不满意

Let's start with some basics. Swing is single threaded, meaning you must never block or execute long running code within the context of the Event Dispatching Thread, this will make the UI freeze and the user upset

Swing不是线程安全的,这意味着您永远不要在EDT上下文之外创建或更新UI。

Swing is NOT thread safe, this means that you should never create or update the UI from outside of the context of the EDT.

这会导致您遇到问题。

This leads you into a problem. You want to, after a some small delay, update the UI.

幸运的是,至少有两种可能,Swing Timer SwingWorker

Lucky for you, there are at least two possibilities, a Swing Timer or a SwingWorker.

Swing Timer 相对简单,但实际上并没有提供在两次更新之间生成可变延迟的方法。 SwingWorker 更为复杂,但是可以使您控制基本执行所需的操作。

A Swing Timer is relatively simple, but doesn't really provide a means to generate a variable delay between updates. A SwingWorker is more complex, but gives you the control to basically do what you want.

这两个(可以)在EDT之外等待,但是两者都提供了可以安全地将更新推送到EDT的方法。

Both of these (can) "wait" outside of the EDT, but both provide means by which you can push updates to the EDT safely.

例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BlinkyTheButton {

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

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

                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 blinky;

        public TestPane() {
            blinky = new JButton("Blinky");
            blinky.setOpaque(true);
            blinky.addActionListener(new ActionListener() {
                private BlinkWorker worker;
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (worker == null || worker.getState() == SwingWorker.StateValue.DONE) {
                        worker = new BlinkWorker(blinky, Color.RED);
                        worker.addPropertyChangeListener(new PropertyChangeListener() {
                            @Override
                            public void propertyChange(PropertyChangeEvent evt) {
                                SwingWorker worker = (SwingWorker) evt.getSource();
                                if ("state".equals(evt.getPropertyName())) {
                                    if (worker.getState() == SwingWorker.StateValue.DONE) {
                                        // this is where you would then call the method to
                                        // update the state for a new question
                                    }
                                }
                            }
                        });
                        worker.execute();
                    }
                }
            });
            setLayout(new GridBagLayout());
            add(blinky);
        }

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

        public class BlinkWorker extends SwingWorker<Void, Color> {

            private JButton btn;
            private Color color;
            private Color normal;

            public BlinkWorker(JButton btn, Color color) {
                this.btn = btn;
                normal = btn.getBackground();
                this.color = color;
            }

            @Override
            protected Void doInBackground() throws Exception {
                for (int index = 10; index > 1; index--) {
                    publish(color);
                    Thread.sleep(index * 100);
                    publish(normal);
                    Thread.sleep(index * 100);
                }
                return null;
            }

            @Override
            protected void process(List<Color> chunks) {
                Color color =  chunks.get(chunks.size() - 1);
                btn.setBackground(color);
            }

        }

    }

}

看看 Swing中的并发如何使用Swing计时器工作线程和SwingWorker 了解更多详情

这篇关于Jbutton在两种背景颜色之间闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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