【问题标题】:Change JButton Text and BackGround Color with Smooth Look以平滑的外观更改 JButton 文本和背景颜色
【发布时间】:2020-11-10 11:20:48
【问题描述】:

我从过去一周开始学习 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这样平滑的按钮的文字和颜色?

谢谢。

【问题讨论】:

  • 我们想利用定时器。看看这个答案:stackoverflow.com/a/5500371/1270000 这是一个很快就会变得复杂的大话题,但简短的版本是所有游戏逻辑都应该在使用invokeAndWait()invokeLater() 启动计时器的单独线程上完成它调用UI线程并使用定时器处理颜色变化,这样就不会阻塞UI,我们可以根据定时器实现无缝的颜色过渡。

标签: java swing jbutton


【解决方案1】:

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

以下代码演示。请注意,我将班级名称更改为MyPanel,以免与班级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);
        });
    }
}

【讨论】:

  • 感谢您的回答,我认为它解决了我的问题(我需要实现它),但我不知道为什么我的代码不起作用?
  • @Srilakshmikanthan 简单地说,在 Swing 中实现动画的唯一方法是通过 javax.swing.Timer 类。
  • 谢谢,定时器生成的ActionEvent参数是虚拟的吗?
猜你喜欢
  • 2014-05-11
  • 1970-01-01
  • 2018-12-25
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
相关资源
最近更新 更多