使用平滑外观更改 JButton 文本和背景颜色

Change JButton Text and BackGround Color with Smooth Look

我从上周开始学习 Swing,我想设计一些像拼图这样的游戏,2048 为了好玩我已经成功地编写了拼图但是在编写 2048 时我遇到了一些问题,请参见下面的示例代码,该代码不是原始的但它说明问题。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

@SuppressWarnings("serial")
class Panel extends JPanel implements ActionListener
{
    JButton[] button = new JButton[4];

    boolean flag = true;

    public Panel()
    {
        this.setLayout(new GridLayout(1,4));

        for(int i = 0; i < 4; ++i)
        {
            button[i] = new JButton("");
            button[i].setBackground(Color.WHITE);
            button[i].addActionListener(this);
            button[i].setPreferredSize(new Dimension(100,100));
            add(button[i]);
        }

        button[0].setText("2");
        button[0].setBackground(Color.GREEN);
    }

    @Override
    public void actionPerformed(ActionEvent Ae)
    {
        if(flag)
        {
            flag = false;

            button[0].setText("");
            button[0].setBackground(Color.WHITE);
            //for(long i = 0; i < 100000000L; ++i);
            button[1].setText("2");
            button[1].setBackground(Color.GREEN);
            //for(long i = 0; i < 100000000L; ++i);
            button[1].setText("");
            button[1].setBackground(Color.WHITE);
            //for(long i = 0; i < 100000000L; ++i);
            button[2].setText("2");
            button[2].setBackground(Color.GREEN);
            //for(long i = 0; i < 100000000L; ++i);
            button[2].setText("");
            button[2].setBackground(Color.WHITE);
            //for(long i = 0; i < 100000000L; ++i);
            button[3].setText("2");
            button[3].setBackground(Color.GREEN);
        }
        else
        {
            flag = true;

            button[0].setText("2");
            button[0].setBackground(Color.GREEN);
            button[1].setText("");
            button[1].setBackground(Color.WHITE);
            button[2].setText("");
            button[2].setBackground(Color.WHITE);
            button[3].setText("");
            button[3].setBackground(Color.WHITE); 
        }
    }
}

public class Grid
{
    public Grid()
    {
        // I cannot ascess JFrame reference in real code too but it is not 
        // must, it would be better that i can do the thing without 
        // JFrame reference.
        JFrame jFrame = new JFrame("Grid");

        jFrame.add(new Panel());
        jFrame.pack();
        jFrame.setResizable(false);
        jFrame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> new Grid());
    }
}

在上面的代码中,按钮文本和颜色的变化不平滑,第一个按钮突然变成白色,最后一个按钮突然变成绿色,所以我测试了第二个和第三个按钮是否通过延迟循环实际改变但第二个和第三个按钮仍然没有改变,但它等待一段时间才能改变第一个按钮和最后一个按钮。我希望这个问题是可以理解的。

注意:实际上我是通过键绑定而不是按钮单击来使用键盘的,我在这里使用它来说明问题。

如何像 2048 game 一样平滑地切换按钮的文本和颜色?

谢谢。

希望我理解你的问题。你想要的是动画。为此,您需要使用 timer.

以下代码演示。请注意,我将 class 名称更改为 MyPanel,以免与 class java.awt.Panel.

冲突
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
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.SwingUtilities;
import javax.swing.Timer;

public class MyPanel extends JPanel implements ActionListener {
    JButton[] button = new JButton[4];
    boolean flag = true;
    Timer timer;
    int currentIndex;
    int delta;

    public MyPanel() {
        this.setLayout(new GridLayout(1, 4));
        for (int i = 0; i < 4; ++i) {
            button[i] = new JButton("");
            button[i].setBackground(Color.WHITE);
            button[i].addActionListener(this);
            button[i].setPreferredSize(new Dimension(100, 100));
            add(button[i]);
        }
        button[0].setText("2");
        button[0].setBackground(Color.GREEN);
        timer = new Timer(500, event -> {
            button[currentIndex].setText("");
            button[currentIndex].setBackground(Color.WHITE);
            currentIndex += delta;
            button[currentIndex].setText("2");
            button[currentIndex].setBackground(Color.GREEN);
            if (currentIndex == 0  ||  currentIndex == 3) {
                timer.stop();
            }
        });
        timer.setInitialDelay(0);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (flag) {
            flag = false;
            delta = 1;
        }
        else {
            flag = true;
            delta = -1;
        }
        timer.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame jFrame = new JFrame("Grid");
            jFrame.add(new MyPanel());
            jFrame.pack();
            jFrame.setResizable(false);
            jFrame.setVisible(true);
        });
    }
}