JFrame 图像点击后更新。

huangapple go评论116阅读模式
英文:

JFrame Image Update on click of image

问题

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class ImageJumble extends JPanel {

    static int difficulty = 0;

    ImageContainer imageContainer;
    JFrame jFrame = new JFrame("Image Jumble");

    private void run() {
        SwingUtilities.invokeLater(this::displayImage);
    }

    public static void main(String[] args) {
        System.out.print("Please enter the difficulty level (1-3): ");
        Scanner scanner = new Scanner(System.in);
        difficulty = scanner.nextInt();

        new ImageJumble().run();
    }

    private void displayImage() {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Please choose an image...");
        FileNameExtensionFilter filter = new FileNameExtensionFilter("JPEG", "jpeg", "jpg", "png", "bmp", "gif");
        fc.addChoosableFileFilter(filter);

        BufferedImage image = null;

        if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fc.getSelectedFile();
            try {
                image = ImageIO.read(selectedFile);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.setSize(image.getWidth(), image.getHeight());
        jFrame.setVisible(true);
        jFrame.setLayout(new GridLayout(difficulty, difficulty, 0, 0));

        imageContainer = new ImageContainer(image, difficulty);

        createImage();
    }

    private void createImage() {
        imageContainer.randomize();
        JLabel[] jLabels = new JLabel[difficulty * difficulty];
        for (int i = 0; i < jLabels.length; i++) {
            JLabel jLabel = new JLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)));
            jFrame.add(jLabel);
            jLabel.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    System.out.println("Clicked!");
                    imageContainer.move(i);
                    jFrame.removeAll();
                    createImage();
                }
            });
        }
    }
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class ImageContainer {
    private List<BufferedImage> bufferedImages = new ArrayList<>();
    private int blankLocation = 0;

    public ImageContainer(BufferedImage image, int difficulty) {
        BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.createGraphics();
        g.drawImage(image, 0, 0, null);
        int width = bi.getWidth();
        int height = bi.getHeight();
        int swidth = width / difficulty;
        int sheight = height / difficulty;

        for (int i = 0; i < difficulty; i++) {
            for (int j = 0; j < difficulty; j++) {
                BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
                bufferedImages.add(bimg);
            }
        }
    }

    public List<BufferedImage> getBufferedImages() {
        return bufferedImages;
    }

    public void setBufferedImages(List<BufferedImage> bufferedImages) {
        this.bufferedImages = bufferedImages;
    }

    public void randomize() {
        int size = bufferedImages.size();
        int width = bufferedImages.get(0).getWidth();
        int height = bufferedImages.get(0).getHeight();
        blankLocation = new Random().nextInt(size);
        bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
    }

    public void move(int i) {
        bufferedImages.set(blankLocation, bufferedImages.get(i));
        blankLocation = i;
    }
}
英文:

tldr; How do you use a MouseEvent on a JFrame object(specifically JLabel) to update the displayed image in the JFrame

I am trying to create a program where an image is broken into tiles and on click of one of those tiles, the program moves the tile to the open space in the image. (See Sliding Puzzle for more information).

I currently am able to select an image, break the image into tiles, and "randomly" remove one of the tiles.

My next step would be, on click of one of the tiles, to swap it with the empty tile (I will work on the "eligibility" of tiles to be swapped at a later time, but for now, just want to be able to swap the tile selected with the current blank tile)

To create my image for a 3x3 grid, I split a bufferedImage into 9 equal pieces, "randomly" blank one of the images, and then display the images in jLabels using GridLayout to line them up.

When I add mouseListeners to each jLabel, I am able to see that I am entering the MouseListener as I can see the console log message "Clicked" as shown below, however, am not able to update the image as desired.

How can I use a MouseEvent on these JFrame JLabels to call a method within ImageContainer(i.e. move()) and update the displayed image?

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class ImageJumble extends JPanel {
static int difficulty = 0;
ImageContainer imageContainer;
JFrame jFrame = new JFrame(&quot;Image Jumble&quot;);
private void run() {
SwingUtilities.invokeLater(this::displayImage);
}
public static void main(String[] args) {
System.out.print(&quot;Please enter the difficulty level (1-3): &quot;);
Scanner scanner = new Scanner(System.in);
difficulty = scanner.nextInt();
new ImageJumble().run();
}
private void displayImage() {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle(&quot;Please choose an image...&quot;);
FileNameExtensionFilter filter = new FileNameExtensionFilter(&quot;JPEG&quot;, &quot;jpeg&quot;, &quot;jpg&quot;, &quot;png&quot;, &quot;bmp&quot;, &quot;gif&quot;);
fc.addChoosableFileFilter(filter);
BufferedImage image = null;
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
try {
image = ImageIO.read(selectedFile);
} catch (IOException ex) {
ex.printStackTrace();
}
}
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(image.getWidth(), image.getHeight());
jFrame.setVisible(true);
jFrame.setLayout(new GridLayout(difficulty,difficulty,0,0));
imageContainer = new ImageContainer(image,difficulty);
createImage();
}
private void createImage() {
imageContainer.randomize();
JLabel[] jLabels = new JLabel[difficulty * difficulty];
for(int i = 0; i &lt; jLabels.length; i++) {
JLabel jLabel = new JLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)));
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println(&quot;Clicked!&quot;);
imageContainer.move(i);
jFrame.removeAll();
createImage();
}
});
}
}
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ImageContainer {
private List&lt;BufferedImage&gt; bufferedImages = new ArrayList&lt;&gt;();
private int blankLocation = 0;
public ImageContainer(BufferedImage image, int difficulty) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, null);
int width = bi.getWidth();
int height = bi.getHeight();
int swidth = width / difficulty;
int sheight = height / difficulty;
for (int i = 0; i &lt; difficulty; i++) {
for (int j = 0; j &lt; difficulty; j++) {
BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
bufferedImages.add(bimg);
}
}
}
public List&lt;BufferedImage&gt; getBufferedImages() {
return bufferedImages;
}
public void setBufferedImages(List&lt;BufferedImage&gt; bufferedImages) {
this.bufferedImages = bufferedImages;
}
public void randomize() {
int size = bufferedImages.size();
int width = bufferedImages.get(0).getWidth();
int height = bufferedImages.get(0).getHeight();
blankLocation = new Random().nextInt(size);
bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
}
public void move(int i) {
bufferedImages.set(blankLocation,bufferedImages.get(i));
blankLocation = i;
}
}

答案1

得分: 2

This answer is based on [this](https://stackoverflow.com/a/57725865/3992939) previous answer, adapted to your code. <br/>
It is a one-file mre : the entire code can be copy-pasted to `ImageJumble.java` file, and run. <br/>
It supports DnD from any grid location to any other. You may want to change it. <br/>Please note the comments:

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class ImageJumble extends JPanel {

    private static int difficulty = 3;
    private static final String FLOWER = "http://www.digitalphotoartistry.com/rose1.jpg";
    private static final int GAP = 4;

    private JPanel content;

    private void run() {
        SwingUtilities.invokeLater(this::displayImage);
    }

    public static void main(String[] args) {
        new ImageJumble().run();
    }

    private void displayImage() {

        BufferedImage bi = null;

        try {
            bi = ImageIO.read(new URL(FLOWER));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        content = new JPanel(new GridLayout(difficulty,difficulty, GAP,GAP));
        createImage(bi);
        JFrame jFrame = new JFrame("Image Jumble");
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.add(content);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    private void createImage( BufferedImage bi) {

        ImageContainer imageContainer = new ImageContainer(bi,difficulty);
        imageContainer.randomize();

        for(int i = 0; i < difficulty * difficulty; i++) {
            content.add(new DragDropPane(imageContainer.getBufferedImages().get(i)));;
        }
    }
}

class ImageContainer {
    private final List<BufferedImage> bufferedImages = new ArrayList<>();
    private int blankLocation = 0;

    public ImageContainer(BufferedImage image, int difficulty) {
        BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.createGraphics();
        g.drawImage(image, 0, 0, null);
        int width = bi.getWidth();
        int height = bi.getHeight();
        int swidth = width / difficulty;
        int sheight = height / difficulty;

        for (int i = 0; i < difficulty; i++) {
            for (int j = 0; j < difficulty; j++) {
                BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
                bufferedImages.add(bimg);
            }
        }
    }

    public List<BufferedImage> getBufferedImages() {
        return bufferedImages;
    }

    public void randomize() {
        Collections.shuffle(bufferedImages);//shuffle images
        int size = bufferedImages.size();
        int width = bufferedImages.get(0).getWidth();
        int height = bufferedImages.get(0).getHeight();
        blankLocation = new Random().nextInt(size);
        bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
    }
}

class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {

    private JComponent dragable;
    private final BufferedImage bi;

    public DragDropPane(BufferedImage bi) {

        setBackground(Color.BLACK);
        this.bi = bi;
        var label = new JLabel(new ImageIcon(bi), JLabel.CENTER);
        setContent(label);
        new MyDropTargetListener(this);
        DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                                        this, DnDConstants.ACTION_COPY, this);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(bi.getWidth(), bi.getHeight());
    }

    public void setContent(JComponent component) {
        removeAll();
        dragable = component;
        add(component);
        repaint();
    }

    //--->DragGestureListener implementation

    @Override
    public void dragGestureRecognized(DragGestureEvent dge) {

        // Create our transferable wrapper
        Transferable transferable = new TransferableComponent(dragable);

        // Start the "drag" process...
        DragSource ds = dge.getDragSource();
        ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
        remove(dragable);
        revalidate(); repaint();
    }

    //--->DragSourceListener implementation

    @Override
    public void dragEnter(DragSourceDragEvent dsde) {}

    @Override
    public void dragOver(DragSourceDragEvent dsde) {}

    @Override
    public void dropActionChanged(DragSourceDragEvent dsde) {}


    @Override
    public void dragExit(DragSourceEvent dse) {}

    @Override
    public void dragDropEnd(DragSourceDropEvent dsde) {
        // If the drop was not successful, we need to
        // return the component back to it's previous
        // parent
        if (!dsde.getDropSuccess()) {
            setContent(dragable);
        }
    }
}

class MyDropTargetListener extends DropTargetAdapter {

    private final DragDropPane target;

    public MyDropTargetListener(DragDropPane target) {
        this.target = target;
        new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
    }

    @Override
    public void drop(DropTargetDropEvent event) {

        try {

            var tr = event.getTransferable();
            var component = (JComponent) tr.getTransferData(TransferableComponent.component);

            if (event.isDataFlavorSupported(TransferableComponent.component)) {

                event.acceptDrop(DnDConstants.ACTION_COPY);
                target.setContent(component);
                event.dropComplete(true);

            } else {
                event.rejectDrop();
            }

        } catch (Exception e) {
            e.printStackTrace();
            event.rejectDrop();
        }
    }
}

class TransferableComponent implements Transferable {

    protected static final DataFlavor component =
            new DataFlavor(JComponent.class, "A Component");

    protected static final DataFlavor[] supportedFlavors = {
            component
    };

    private final JComponent componentToTransfer;

    public Transferable

<details>
<summary>英文:</summary>

This answer is based on [this](https://stackoverflow.com/a/57725865/3992939) previous answer, adapted to your code. &lt;br/&gt;
It is a one-file mre : the entire code can be copy-pasted to `ImageJumble.java` file, and run. &lt;br/&gt;
It supports DnD from any grid location to any other. You may want to change it. &lt;br/&gt;Please note the comments:
	
	import java.awt.Color;
	import java.awt.Cursor;
	import java.awt.Dimension;
	import java.awt.Graphics;
	import java.awt.GridLayout;
	import java.awt.datatransfer.DataFlavor;
	import java.awt.datatransfer.Transferable;
	import java.awt.datatransfer.UnsupportedFlavorException;
	import java.awt.dnd.DnDConstants;
	import java.awt.dnd.DragGestureEvent;
	import java.awt.dnd.DragGestureListener;
	import java.awt.dnd.DragSource;
	import java.awt.dnd.DragSourceDragEvent;
	import java.awt.dnd.DragSourceDropEvent;
	import java.awt.dnd.DragSourceEvent;
	import java.awt.dnd.DragSourceListener;
	import java.awt.dnd.DropTarget;
	import java.awt.dnd.DropTargetAdapter;
	import java.awt.dnd.DropTargetDropEvent;
	import java.awt.image.BufferedImage;
	import java.io.IOException;
	import java.net.URL;
	import java.util.ArrayList;
	import java.util.Collections;
	import java.util.List;
	import java.util.Random;
	
	import javax.imageio.ImageIO;
	import javax.swing.ImageIcon;
	import javax.swing.JComponent;
	import javax.swing.JFrame;
	import javax.swing.JLabel;
	import javax.swing.JPanel;
	import javax.swing.SwingUtilities;
	import javax.swing.WindowConstants;
	
	public class ImageJumble extends JPanel {
	
	    private static int difficulty = 3;
		private static final String FLOWER = &quot;http://www.digitalphotoartistry.com/rose1.jpg&quot;;
		private static final int GAP = 4;
	
	    private JPanel content;
	
	    private void run() {
	        SwingUtilities.invokeLater(this::displayImage);
	    }
	
	    public static void main(String[] args) {
	        new ImageJumble().run();
	    }
	
	    private void displayImage() {
	
	        BufferedImage bi = null;
	
	        try {
	            bi = ImageIO.read(new URL(FLOWER));
	        } catch (IOException ex) {
	            ex.printStackTrace();
	        }
			content = new JPanel(new GridLayout(difficulty,difficulty, GAP,GAP));
	        createImage(bi);
		    JFrame jFrame = new JFrame(&quot;Image Jumble&quot;);
	        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	        jFrame.add(content);
	        jFrame.pack();
	        jFrame.setVisible(true);
	    }
	
	    private void createImage( BufferedImage bi) {
	
	        ImageContainer imageContainer = new ImageContainer(bi,difficulty);
	        imageContainer.randomize();
	
	        for(int i = 0; i &lt; difficulty * difficulty; i++) {
	            content.add(new DragDropPane(imageContainer.getBufferedImages().get(i)));;
	        }
	    }
	}
	
	class ImageContainer {
	    private final List&lt;BufferedImage&gt; bufferedImages = new ArrayList&lt;&gt;();
	    private int blankLocation = 0;
	
	    public ImageContainer(BufferedImage image, int difficulty) {
	        BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
	        Graphics g = bi.createGraphics();
	        g.drawImage(image, 0, 0, null);
	        int width = bi.getWidth();
	        int height = bi.getHeight();
	        int swidth = width / difficulty;
	        int sheight = height / difficulty;
	
	        for (int i = 0; i &lt; difficulty; i++) {
	            for (int j = 0; j &lt; difficulty; j++) {
	                BufferedImage bimg = bi.getSubimage(j * swidth, i * sheight, swidth, sheight);
	                bufferedImages.add(bimg);
	            }
	        }
	    }
	
	    public List&lt;BufferedImage&gt; getBufferedImages() {
	        return bufferedImages;
	    }
	
	    public void randomize() {
	    	Collections.shuffle(bufferedImages);//shuffle images
	        int size = bufferedImages.size();
	        int width = bufferedImages.get(0).getWidth();
	        int height = bufferedImages.get(0).getHeight();
	        blankLocation = new Random().nextInt(size);
	        bufferedImages.set(blankLocation, new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB));
	    }
	}
	
	class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {
	
		private JComponent dragable;
		private final BufferedImage bi;
	
		public DragDropPane(BufferedImage bi) {
	
			setBackground(Color.BLACK);
			this.bi = bi;
			var label = new JLabel(new ImageIcon(bi), JLabel.CENTER);
			setContent(label);
			new MyDropTargetListener(this);
			DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
											this, DnDConstants.ACTION_COPY, this);
		}
	
		@Override
		public Dimension getPreferredSize() {
			return new Dimension(bi.getWidth(), bi.getHeight());
		}
	
		public void setContent(JComponent component) {
			removeAll();
			dragable = component;
			add(component);
			repaint();
		}
	
		//--&gt;DragGestureListener implementation
	
		@Override
		public void dragGestureRecognized(DragGestureEvent dge) {
	
			// Create our transferable wrapper
			Transferable transferable = new TransferableComponent(dragable);
	
			// Start the &quot;drag&quot; process...
			DragSource ds = dge.getDragSource();
			ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
			remove(dragable);
			revalidate(); repaint();
		}
	
		//--&gt;DragSourceListener implementation
	
		@Override
		public void dragEnter(DragSourceDragEvent dsde) {}
	
		@Override
		public void dragOver(DragSourceDragEvent dsde) {}
	
		@Override
		public void dropActionChanged(DragSourceDragEvent dsde) {}
	
	
		@Override
		public void dragExit(DragSourceEvent dse) {}
	
		@Override
		public void dragDropEnd(DragSourceDropEvent dsde) {
			// If the drop was not successful, we need to
			// return the component back to it&#39;s previous
			// parent
			if (!dsde.getDropSuccess()) {
				setContent(dragable);
			}
		}
	}
	
	class MyDropTargetListener extends DropTargetAdapter {
	
	    private final DragDropPane target;
	
	    public MyDropTargetListener(DragDropPane target) {
	        this.target = target;
	        new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
	    }
	
	    @Override
		public void drop(DropTargetDropEvent event) {
	
	        try {
	
	            var tr = event.getTransferable();
	            var component = (JComponent) tr.getTransferData(TransferableComponent.component);
	
	            if (event.isDataFlavorSupported(TransferableComponent.component)) {
	
	                event.acceptDrop(DnDConstants.ACTION_COPY);
	                target.setContent(component);
	                event.dropComplete(true);
	
	            } else {
					event.rejectDrop();
				}
	
	        } catch (Exception e) {
	            e.printStackTrace();
	            event.rejectDrop();
	        }
	    }
	}
	
	class TransferableComponent implements Transferable {
	
	    protected static final DataFlavor component =
	            new DataFlavor(JComponent.class, &quot;A Component&quot;);
	
	    protected static final DataFlavor[] supportedFlavors = {
	            component
	    };
	
	    private final JComponent componentToTransfer;
	
	    public TransferableComponent(JComponent componentToTransfer) {
	
	        this.componentToTransfer = componentToTransfer;
	    }
	
	    @Override
		public DataFlavor[] getTransferDataFlavors() {
	
	        return supportedFlavors;
	    }
	
	    @Override
		public boolean isDataFlavorSupported(DataFlavor flavor) {
	
	        return flavor.equals(component);
	    }
	
	    @Override
		public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
	
	        if (flavor.equals(component)) return componentToTransfer;
			else  throw new UnsupportedFlavorException(flavor);
	    }
	}

&lt;hr&gt;

[![enter image description here][1]][1]


  [1]: https://i.stack.imgur.com/GXLCj.gif

</details>



# 答案2
**得分**: 1

不要移除/添加组件而只需交换图标

1. 使用一个带有GridLayout的JPanel其中包含每个网格中的JLabel
2. 为每个JLabel添加一个ImageIcon除了一个JLabel)。
3. 为每个JLabel添加一个MouseListner
4. 在mouseClicked事件中您可以获取被点击的标签然后移除ImageIcon并将图标添加到空标签中

因此当您创建面板时可以有一个名为`emptyLabel`的变量它将被初始化为没有图标的标签然后mouseClicked中的逻辑可能是这样的

```java
JLabel clicked = (JLabel)e.getSource();
emptyLabel.setIcon(clicked.getIcon());
emptyLabel = clicked;
英文:

Don't remove/add components. Instead just swap the Icon.

  1. Use a JPanel with a GridLayout that contains a JLabel in each grid
  2. Add an ImageIcon to each JLabel (except for one)
  3. Add a MouseListner to each JLabel.
  4. In the mouseClicked event you get the label that was clicked and remove the ImageIcon and add the Icon to the empty label.

So when you create the board you could have a variable like emptyLabel which would be initialized to the label without the Icon. Then the logic in the mouseClicked might be something like:

JLabel clicked = (JLabel)e.getSource();
emptyLabel.setIcon( clicked.getIcon() );
emptyLabel = clicked;

答案3

得分: 0

创建一个自定义的JLabel类来保存位置(i):

class MyImageLabel extends JLabel {
    private int position;
    public MyImageLabel(Icon image, int position) {
        super(image);
        this.position = position;
    }
    public int getPosition() {
        return position;
    }
}

createImage中适应实例化这个类,而不是实例化JLabel,并且在mouseListener中可以调用getPosition()

for (int i = 0; i < jLabels.length; i++) {
    MyImageLabel jLabel = new MyImageLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)), i);
    jFrame.add(jLabel);
    jLabel.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
            System.out.println("Clicked!");
            imageContainer.move(jLabel.getPosition());
            jFrame.removeAll();
            createImage();
        }
    });
}
英文:

Create a custom JLabel class to hold the position (i):

class MyImageLabel extends JLabel {
private int position;
public MyImageLabel(Icon image,int position) {
super(image);
this.position=position;
}
public int getPosition()
{
return position;
}
}

Adapt createImage to instantiate this class instead of JLabels and in the mouseListener you can call getPosition():

    for(int i = 0; i &lt; jLabels.length; i++) {
MyImageLabel jLabel = new MyImageLabel(new ImageIcon(imageContainer.getBufferedImages().get(i)),i);
jFrame.add(jLabel);
jLabel.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println(&quot;Clicked!&quot;);
imageContainer.move(jLabel.getPosition());
jFrame.removeAll();
createImage();
}
});
}

答案4

得分: 0

我的建议是不要在JFrame对象上调用.add.removeAll方法,而是创建一个带有GridLayout的新JPanel,并使用jframe.getContentPanel().add(labelsPanel)进行添加。如果界面没有刷新,您可以在您的JPanel上调用revalidate()方法。

英文:

My advice is not to call .add and .removeAll on the JFrame object but create a new JPanel with the GridLayout and use jframe.getContentPanel().add(labelsPanel). If it doesn't refresh you can then call revalidate() on your JPanel.

huangapple
  • 本文由 发表于 2020年10月20日 21:49:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64446565.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定