0

I am learning Swing from past week and I want desing some game like puzzle, 2048 for fun i have written puzzle sucessfully but when writting 2048 i encountered some problem, see below for sample code that is not orginal but it states the problem.

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

In above code the change of button text and color is not smooth that is first button suddenly becomes white and last button suddnley becomes Green, so i have tested that second and third button is actullay changing or not by the delay loop but still second and third button is not changing but it waits some time to change first button and last button. I Hope that the problem is understandable.

Note: In real i use keybord by keybinding not button click i used it here for state the problem.

How To switch text and color of button with smooth look like 2048 game ?

Thanks.

srilakshmikanthanp
  • 2,231
  • 1
  • 8
  • 25
  • We want to make use of timers. Take a look at this answer: https://stackoverflow.com/a/5500371/1270000 This is a big topic that can get complicated quickly, but the short version is that all game logic should be done on a separate thread that uses `invokeAndWait()` or `invokeLater()` to start a timer which calls the UI thread and process the colour change using timers, this way there is no blocking of the UI, and we can achieve a seamless colour transition based on the timers. – sorifiend Nov 10 '20 at 11:53

1 Answers1

1

Hopefully I understood your problem. What you want is animation. To do this you need to use a timer.

The following code demonstrates. Note that I changed the class name to MyPanel so as not to clash with 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);
        });
    }
}
Abra
  • 19,142
  • 7
  • 29
  • 41