JPanel in puzzle game not updating

I have a simple puzzle game. There is an image consisting of 16 tiles (randomly placed). Images are stored in an array, and when the game starts, they are added to the main JPanel.

alt text

The game works as follows: each image has the attributes "place" and "number". โ€œLocationโ€ is the current location on the grid (correct or not), and โ€œnumberโ€ is the desired location for the image. When the user clicks on the image, his attributes "place" and "number" are checked. If they match, nothing happens. If not, the game checks to see if any image is in memory. If it is not, then this image "place" and "number" are saved. If there is any image in the memory, then the currently selected image "plac'e" is checked with the saved image "number". When they coincide, their places change. This part is working correctly. But now I call the addComponent method on my JPanel with updated images, and nothing just happens. Shouldn't new images be added to JPanel instead of old ones?

bonus package;

import javax.swing.*; import java.util.Random; import java.awt.event.*; import java.awt.*; class Puzzle extends JPanel implements ActionListener { private int selected_nr=-1; private int selected_pl=-1; private boolean memory=false; private static Img[] images; public Puzzle(){ JFrame f = new JFrame("Smile"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(this); f.setSize(252,252); f.setVisible(true); setLayout(new GridLayout(4, 4)); images = new Img[16]; int[] buttons = new int[16]; for(int i=0; i<16; i++){ buttons[i] = i; } int rand; int temp; Random random; random = new Random(System.currentTimeMillis()); for (int i = 0; i < buttons.length; i++) { rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length; temp = buttons[i]; buttons[i] = buttons[rand]; buttons[rand] = temp; } for (int i = 0; i < 16; i++) { images[i] = new Img(i, buttons[i]); } addComponents(images); } public void addComponents(Img[] im){ this.removeAll(); for(int i=0; i<16; i++){ im[i].addActionListener(this); im[i].setPreferredSize(new Dimension(53,53)); add(im[i]); } this.validate(); } public void actionPerformed(ActionEvent e) { Img b = (Img)(e.getSource()); int num = b.getNumber(); int pl = b.getPlace(); if(!(b.rightPlace())){ if(memory){ if(pl == selected_nr){ images[pl].setPlace(selected_pl); images[selected_pl].setPlace(selected_nr); selected_nr = -1; selected_pl = -1; memory = false; addComponents(images); } else{ System.out.println("Try other image"); } } else{ memory = true; selected_nr = num; selected_pl = pl; } } else{ System.out.println("OK !"); } } public static void main(String args[]) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new Puzzle(); } }); } } class Img extends JButton { int number; int place; ImageIcon img; public Img(int p, int n){ number = n; place = p; img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER); setIcon(img); } public boolean rightPlace(){ boolean correct=false; if(number == place){ correct = true; } return correct; } public void setPlace(int i){ place = i; } public int getNumber(){ return number; } public int getPlace(){ return place; } } 

UPDATE: Changed the code for using answers, but still no luck. addComponents () receives updated images [], but does not check them again.

+6
source share
3 answers

After changing the components, you need to โ€œupdateโ€ the Swing component by calling invalidate() or revalidate() .

+3
source

Instead of relying on files with a preview image, here is an example of slicing an existing image and shuffling the resulting shapes. It combines useful (+1) sentences with both @Frederick and @akf.

enter image description here

 import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer; public class ImageLabelPanel extends JPanel implements ActionListener { private static final int N = 4; private final List<JLabel> list = new ArrayList<JLabel>(); private final Timer timer = new Timer(1000, this); ImageLabelPanel() { this.setLayout(new GridLayout(N, N)); BufferedImage bi = null; try { bi = ImageIO.read(new File("image.jpg")); } catch (IOException e) { e.printStackTrace(); } for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { int w = bi.getWidth() / N; int h = bi.getHeight() / N; BufferedImage b = bi.getSubimage(c * w, r * h, w, h); list.add(new JLabel(new ImageIcon(b))); } } createPane(); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(this); f.pack(); f.setVisible(true); timer.start(); } private void createPane() { this.removeAll(); for (JLabel label : list) add(label); this.validate(); } @Override public void actionPerformed(ActionEvent e) { Collections.shuffle(list); createPane(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new ImageLabelPanel(); } }); } } 
+12
source

You add all your components to your JPanel again without actually removing them. In your addComponents() method, I first call removeAll() . You might want to rename this method to highlight side effects, as it will no longer be just adding components. Perhaps resetComponents() would be better.

+4
source

All Articles