0

我正在尝试制作像 simon 这样的游戏:http ://www.freegames.ws/games/kidsgames/simon/simon.htm#

我正在制作一个只有 2 个按钮的较小比例尺。我希望颜色在 2 个按钮、按钮 1 和按钮 2 之间切换。这是在一个线程中,因为我需要在发生这种情况时单击按钮。当我打开程序时,按钮颜色保持原样。

提前感谢您的帮助!

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;

import javax.swing.*;

public class TestFrame extends JFrame{

    public JButton button1; 
    public JButton button2;

    boolean isTrue = true;
    boolean switchColor = true;

    TestFrame(){
        super("Simon");
        initialize();

        this.setSize(200, 400);
        this.setVisible(true);
    }

    private void initialize() {
         this.setLayout(new BorderLayout()); 

        button1 = new JButton();
        button1.setBackground(Color.green);
        button1.setSize(200,200);

        button2 = new JButton();
        button2.setSize(200, 200);
        button2.setBackground(Color.blue);

        this.add(button1, BorderLayout.NORTH);
        this.add(button2, BorderLayout.SOUTH);
        Thread t = new Thread(r1);
        t.start();

    }
    Runnable r1 = new Runnable() {
        public void run() {
            while(isTrue){
            if(switchColor = true){
                button1.setBackground(Color.blue);
                button2.setBackground(Color.green);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                refresh();
                switchColor = false;
            } else {
                button1.setBackground(Color.green);
                button2.setBackground(Color.blue);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                refresh();

                switchColor = true;
                }
            }

        }
    };

    public void refresh(){
        this.invalidate();
        this.validate();
        this.repaint();
    }

}
4

2 回答 2

2

有一些问题很突出(shazin 已经解决了一个),另一个让我害怕的是你违反了 Swing 的单线程要求。对 UI 的所有更改都必须在事件调度线程的上下文中进行。

而不是使用 a Thread,您应该使用 a javax.swing.Timer。这将使您无需将更新重新同步回 EDT。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
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 FlashyButtons {

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

    public FlashyButtons() {
        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.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JButton btn1;
        private JButton btn2;
        private int count = 0;

        public TestPane() {
            setLayout(new GridBagLayout());
            btn1 = new FlashButton();
            btn2 = new FlashButton();
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(btn1, gbc);
            add(btn2, gbc);

            btn1.setBackground(Color.GREEN);
            btn2.setBackground(Color.BLUE);

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    count++;
                    if (count % 2 == 0) {
                        btn1.setBackground(Color.BLUE);
                        btn2.setBackground(Color.GREEN);
                    } else {
                        btn1.setBackground(Color.GREEN);
                        btn2.setBackground(Color.BLUE);
                    }
                }
            });
            timer.start();
        }

    }

    public class FlashButton extends JButton {

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

    }

}

查看Swing 中的并发以获取更多详细信息

于 2013-08-07T01:36:30.857 回答
0
if(switchColor = true){
    button1.setBackground(Color.blue);
    button2.setBackground(Color.green);
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    refresh();
    switchColor = false;
} else {
    button1.setBackground(Color.green);
    button2.setBackground(Color.blue);
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    refresh();

    switchColor = true;
    }
}

在上面的代码中,将以下内容更改为

if(switchColor = true){

if(switchColor == true){ 

要不就

if(switchColor){

最好在里面有你的 Runnable 匿名类

SwingUtilities.invokeLater(new Runnable() {
    public void run() {

    }
});

而不是使用新的 Thread 对象来创建和启动线程,因为它将更改 Swing UI 属性。

于 2013-08-07T01:20:42.513 回答