JPanel в игре-головоломке не обновляется - PullRequest
6 голосов
/ 20 июня 2010

У меня простая игра-головоломка. Существует изображение, состоящее из 16 плиток (размещенных случайным образом). Изображения хранятся в массиве, и при запуске игры они добавляются в главную JPanel.

альтернативный текст http://img248.imageshack.us/img248/7403/27632947.gif

Игра работает следующим образом: каждое изображение имеет атрибуты «место» и «номер». «Место» - это текущее место на сетке (правильное или нет), а «число» - желаемое место для изображения. Когда пользователь нажимает на изображение, проверяются его атрибуты «место» и «номер». Если они совпадают, ничего не происходит. Если нет, игра проверяет, находится ли какое-либо изображение в памяти. Если их нет, то «место» и «номер» этого изображения сохраняются. Если в памяти есть какое-то изображение, тогда 'plac'e' выбранного изображения проверяется с помощью 'номера' сохраненного изображения. Когда они совпадают - их места меняются. Эта часть работает правильно. Но теперь я вызываю метод addComponent на моем JPanel с обновленными изображениями, и просто ничего не происходит. Не следует ли добавлять новые изображения в 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 () получает обновленные изображения [], но не проверяет их заново.

Ответы [ 3 ]

12 голосов
/ 20 июня 2010

Вместо того, чтобы полагаться на предварительно вырезанные файлы изображений, вот пример нарезки существующего изображения и перетасовки результирующих частей. Он объединяет полезные (+1) предложения как @Frederick, так и @ 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();
            }
        });
    }
}
4 голосов
/ 20 июня 2010

Вы снова добавляете все свои компоненты в JPanel, фактически не удаляя ни одного из них.В вашем методе addComponents() я бы сначала вызвал removeAll().Возможно, вы захотите переименовать этот метод, чтобы выделить побочные эффекты, поскольку он больше не будет только добавлять компоненты.Возможно, resetComponents() будет лучше.

3 голосов
/ 20 июня 2010

После изменения компонентов вам необходимо «обновить» компонент Swing, вызвав invalidate() или revalidate().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...