JPanel в головоломке, не обновляющей

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

alt text

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

6
задан Glorfindel 30 July 2019 в 07:08
поделиться

3 ответа

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

3
ответ дан 8 December 2019 в 12:18
поделиться

Вместо того, чтобы полагаться на предварительно вырезанные файлы изображений, вот пример нарезки существующего изображения и перетасовки результирующих частей. Он сочетает в себе полезные (+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();
            }
        });
    }
}
12
ответ дан 8 December 2019 в 12:18
поделиться

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

4
ответ дан 8 December 2019 в 12:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: