JPanel在益智游戏不更新
我有一个简单的益智游戏。 有一个由16个瓷砖(随机放置)组成的图像。 图像存储在一个数组中,当游戏启动时,它们被添加到主JPanel。
替代文字http://img248.imageshack.us/img248/7403/27632947.gif
游戏以这种方式工作:每个图像都有属性“地点”和“数字”。 “地点”是网格上的当前位置(无论是否正确),“数字”是图像的理想位置。 当用户点击图片时,他们的“地点”和“数字”属性被检查。 如果他们没有任何反应。 如果没有游戏检查是否有任何图像目前在内存中。 如果没有,则存储该图像的“地点”和“号码”。 如果在内存中有一些图像,则用存储的图像的“数字”检查当前点击的图像的平面。 当他们匹配 – 他们的地方交换。 这部分工作正常。 但现在,我调用我的JPanel更新的图像addComponent方法,根本没有任何反应。 不应该把新的图像添加到JPanel替换旧的?
包奖金;
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; } }
编辑:改变了代码使用的答案,但仍然没有运气。 addComponents()获取更新的图像[],但不重新验证它们。
更改组件后,需要通过调用invalidate()
或revalidate()
来“刷新”Swing组件。
而不是依靠预先裁剪的图像文件,这里是一个切片现有的图像和洗牌结果片断的例子。 它结合了@Frederick和@akf的有用(+1)建议。
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(); } }); } }
您将所有组件再次添加到您的JPanel,而不实际删除它们中的任何一个。 在你的addComponents()
方法中,我将首先调用removeAll()
。 您可能需要重命名该方法以突出副作用,因为它不再只是添加组件。 也许, resetComponents()
会更好。