Java绘制图像方法

问题描述 投票:0回答:4

我正在尝试在练习中将一组 Picture 对象放入 ArrayList 中,然后随机打乱它们并将它们显示为 3x3 的网格。但是,随机播放方法对我来说无法正常工作。或者也许我在绘制或绘制图像方法中做错了什么,我不知道。 我总是看到 9 块图片按其原始顺序显示,而不是随机洗牌。

请参阅下面我的 PicturePiece 类以及主类。

package lab;

import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import javax.imageio.ImageIO;


public class PicturePiece {


    private int IMAGE_X = 266;
    private int IMAGE_Y = 224;
    private final int row;
    private final int col;
    private Image img;
    private static int count = 0;
    private int id = 0;

    public PicturePiece(int row, int col, File f) {
        try {
            this.img = ImageIO.read(f);
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.row = this.IMAGE_X * row;
        this.col = this.IMAGE_Y * col;
        PicturePiece.count++;
        this.id = PicturePiece.count;
    }

    public void draw(Graphics2D g2) {
        g2.drawImage(this.img, this.row, this.col, null);
    }

    public void setPosition(int row, int col) {
        this.IMAGE_X = row;
        this.IMAGE_Y = col;
    }

    public int getXposition() {
        return this.IMAGE_X;
    }

    public int getYposition() {
        return this.IMAGE_Y;
    }

    public int getRow() {
        return this.row;
    }

    public int getCol() {
        return this.col;
    }

    public String getImage() {
        return this.img.toString();
    }

    public static int getPictureCount() {
        return PicturePiece.count;
    }

    public int getId() {
        return this.id;
    }
}

这是我的主课:

/* 从互联网上查找漂亮的图像并使用图像编辑器将其分解 分成 9 个部分(例如,您可以使用 Windows 中的“画图”应用程序)。 以随机顺序在 3×3 网格中显示 9 个图像。添加鼠标监听器。 允许用户通过单击来交换两个图像。 游戏的目标是重新创建原始图像。 当用户获胜时显示适当的消息。 */

package lab;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.*;

public class Puzzle {

    public static void main(String[] args) throws Exception {
        MyFrame frame = new MyFrame();
        frame.setSize(1000, 1000);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class MyFrame extends JFrame {

    MyPanel p;

    public MyFrame() {
        p = new MyPanel();
        add(p);

        setVisible(true);

    }

}    

class MyPanel extends JPanel {

    private ArrayList<PicturePiece> images = new ArrayList<PicturePiece>();

    public MyPanel() {
        this.setFocusable(true);
        try {

            int j = 0, k = 0, pocet = 0;
            for (int i = 1; i <= 9; i++) {

                //g2.drawImage(images.get(i), (IMAGE_X * (j)), (IMAGE_Y * (k)), null);
                images.add(new PicturePiece(j, k, new File(("/home/ivo/Pictures/domcek/domcek" + i + ".jpg"))));

                pocet++;
                //System.out.println("j = " + (j - 1) + "; k = " + (k - 1) + "; i = " + i + "; pocet = " + pocet);
                if ((pocet % 3) == 0) {
                    j = 0;
                    k++;

                } else {
                    j = j + 1;
                }

            }

        } catch (Exception e) {
        }

        //Random rnd = new Random();
        //rnd.setSeed(400);
        //Collections.shuffle(images, rnd);
        Collections.shuffle(images);
      }

    public void draw(Graphics2D g2) {
        try {

            for (int i = 0; i <= images.size(); i++) {
                images.get(i).draw(g2);
           }

        } catch (Exception my) {
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        draw(g2);      
    }
}
java swing draw paintcomponent drawimage
4个回答
1
投票

出现错误是因为您在 MyPanel 函数中设置行/列(j 和 k)。

因此,随机播放只会更改列表中 PicturePiece 的顺序,而不是您用于该位置的 j/k。

为了实现您想要的行为,我将根据列表中的顺序生成行/列。


1
投票

问题在于您根据初始坐标绘制图像,即使您将它们混在一起,PicturePiece 对象中的坐标也保持不变。

简短的解决方案:

图片片段的变化:

public void draw(Graphics2D g2, int i, int j) {
    g2.drawImage(this.img, this.IMAGE_X *i, this.IMAGE_Y * j, null);
}

谜题变化:

public void draw(Graphics2D g2) {
    try {


        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.println(i*3+j);
                images.get(i*3+j).draw(g2, i ,j);
            }
        }

    } catch (Exception my) {
    }
}

这样,您将从数组中以相同的顺序获取图像,但如果它们在数组内打乱,则每次执行时图像都会不同。

注意:这是一个硬编码版本(仅适用于 3x3 矩阵),但我希望您明白了。对此还有很多其他解决方案,但这是我能想到的最短的解决方案。


1
投票

与其在

JPanel/JComponent
上绘图,不如使用
JLabel
来实现此目的,这将使您的工作更轻松,因为您只需担心索引位置。

这是一个例子:

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.*;

public class TestingImages {
    private static final String IMAGE_HEADER = "/images/windowicon/windowicon";
    private GUIView guiView;

    private void performTask () {
        try {
            guiView = new GUIView (IMAGE_HEADER);
        } catch (Exception exp) {
            exp.printStackTrace ();
        }
        Runnable runnable = new Runnable () {
            @Override
            public void run () {
                guiView.displayGUI ();
            }
        };
        EventQueue.invokeLater (runnable);
    }

    public static void main (String[] args) {
        new TestingImages ().performTask ();
    }
}

class GUIView {

    private static final int ROWS = 3;
    private static final int COLUMNS = 3;
    private static final int GAP = 5;
    private static final int TOTAL_IMAGES = 9;

    private JLabel originalImageLabel;
    private JLabel[] splitImageLabel;

    private int counter;
    private int[] imageMap;
    private int previousIndex;
    private int currentIndex;

    private MouseAdapter labelAdapter = new MouseAdapter () {
        private int counter = 0;
        @Override
        public void mouseClicked (MouseEvent me) {
            JLabel label = (JLabel) me.getSource ();
            if (counter == 0) {
                /*
                 * On first click, we simply keeping track of on which label 
                 * the user clicked in the first place
                 */
                previousIndex = findLabelIndex (label);
                System.out.println("Previous Index: " + previousIndex);
                counter = 1;
            } else if (counter == 1) {
                /*
                 * On second click, firstly we will get the location of the JLabel
                 * on which the user clicked, then we will simply swap the icon as 
                 * well as the Name of this JLabel with the JLabel at previousIndex
                 */
                currentIndex = findLabelIndex (label);
                System.out.println("Current Index: " + currentIndex);
                ImageIcon tempIcon = (ImageIcon) splitImageLabel[previousIndex].getIcon ();
                splitImageLabel[previousIndex].setIcon (splitImageLabel[currentIndex].getIcon ());
                splitImageLabel[currentIndex].setIcon (tempIcon);
                String labelName = splitImageLabel[previousIndex].getName ();
                splitImageLabel[previousIndex].setName (splitImageLabel[currentIndex].getName ());
                splitImageLabel[currentIndex].setName (labelName);
                prepareModel ();
                counter = 0;
            }
            if (hasWon()) {
                System.out.println("CONGRATULATIONS you won :-)");
            }
        }
    };

    public GUIView (String imageHeader) throws IOException {
        imageMap = new int[TOTAL_IMAGES];
        counter = 0;
        originalImageLabel = new JLabel ();
        originalImageLabel.setIcon (new ImageIcon (
            ImageIO.read (GUIView.class.getResource (
                                imageHeader + ".jpg"))));
        splitImageLabel = new JLabel[TOTAL_IMAGES];
        for (int i = 0; i < ROWS; ++i) {
            for (int j = 0; j < COLUMNS; ++j) {
                splitImageLabel[counter] = new JLabel ();               
                String indexValue = "" + counter;
                /*
                 * Since JLabel[] is a 1-D Array, hence we simply giving 
                 * each JLabel, at each index a name, as 0 1 2 3 and so on
                 */
                splitImageLabel[counter].setName (indexValue);
                splitImageLabel[counter].setIcon (new ImageIcon (ImageIO.read (
                    GUIView.class.getResource (imageHeader + i + "-" + j + ".png"))));
                splitImageLabel[counter].addMouseListener (labelAdapter);
                ++counter;
            }
        }
    }

    public void displayGUI () {
        JFrame frame = new JFrame("Testing Images");
        frame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel ();
        contentPane.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP));
        contentPane.setLayout (new GridLayout (2, 1, GAP, GAP));

        JPanel headerPanel = new JPanel ();
        headerPanel.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP));
        headerPanel.add (originalImageLabel);
        contentPane.add (headerPanel);

        JPanel footerPanel = new JPanel ();
        footerPanel.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP));
        footerPanel.setLayout (new GridLayout (ROWS, COLUMNS, GAP, GAP));
        /*
         * This will Shuffle the JLable[] array
         */
        Collections.shuffle (Arrays.asList (splitImageLabel));
        prepareModel ();
        for (int i = 0; i < TOTAL_IMAGES; ++i) {
            footerPanel.add (splitImageLabel[i]);
        }

        contentPane.add (footerPanel);

        frame.setContentPane (contentPane);
        frame.pack ();
        frame.setLocationByPlatform (true);
        frame.setVisible (true);
    }

    private int findLabelIndex (JLabel label) {
        int index = 0;
        for (int i = 0; i < TOTAL_IMAGES; ++i) {
            if (label.getName ().equals(splitImageLabel[i].getName ())) {
                index = i;
                break;
            }
        }
        return index;
    }

    /*
     * hasWon() is used to simply check, if the array has values
     * 0 1 2 3 4 till TOTAL_IMAGES, i.e. in increasing order, then it
     * means, that the image has been rightly placed, by the user.
     * Hence, the GAME is OVER
     */
    private boolean hasWon () {
        boolean flag = true;
        for (int i = 0; i < TOTAL_IMAGES; ++i) {
            if (imageMap[i] != i) {
                flag = false;
            }
        }
        return flag;
    }

    /*
     * PrepareModel() is used to assign values to imageMap[] array,
     * in the same sequence, in which the JLabel is placed inside
     * JLabel[] array. Say JLabel[] array has JLabels with names in 
     * this order 1 5 4 3 and so on, thus imageMap[] will contain
     * values 1 5 4 3 and so on, once they are in sorted order, then
     * we can easily check for winning condition
     */
    private void prepareModel () {
        System.out.println("Preparing MODEL");
        for (int i = 0; i < TOTAL_IMAGES; ++i) {
            imageMap[i] = getIntValue(splitImageLabel[i].getName ());
            System.out.println("i: " + i + " Name: " + splitImageLabel[i].getName ());
        }
        System.out.println("Exiting MODEL");
    }

    private int getIntValue (String text) {
        int value = 0;
        try {
            value = Integer.parseInt (text);
        } catch (Exception exp) {
            exp.printStackTrace ();
        }

        return value;
    }
}

输出:

INITIALFINALOUTPUT

CMDOUTPUT

使用的图像:

  1. 原始图片: https://i.sstatic.net/cfpYR.jpg
  2. 对于 SPLIT,我使用了这个网站: http://imagesplitter.net/

1
投票

我这样写了我的应用程序/实验室:

    package lab;

    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.io.File;
    import javax.imageio.ImageIO;
    import javax.swing.JPanel;

    public class PicturePiece extends JPanel {

        private Image img;
        private int id = 0;

        public PicturePiece(int id) {
            this.id = id;
        }

        public void setImage(File f) {
            try {
                this.img = ImageIO.read(f);
            } catch (Exception e) {
            }
        }

        public String getImage() {
            return this.img.toString();
        }

        public int getId() {
            return this.id;
        }
   
        public void draw(Graphics2D g2, int row, int col) {
            g2.drawImage(this.img, row, col, null);

        }

    }


    /**
     * Find a pretty image from the Internet and use an image editor to break it
     * down into 9 pieces (for example, you can use the application Paint in
     * Windows). Display the 9 images in a 3×3 grid in a random order. Add a mouse
     * listener. Allow the user to swap two images by clicking on them. The goal of
     * the game is to re-create the original image. Display an appropriate message
     * when the user wins.
     */
    package lab;

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.geom.Rectangle2D;
    import java.io.File;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import java.util.*;

    public class Puzzle {

    public static void main(String[] args) throws Exception {
        MyFrame frame = new MyFrame();
        frame.setSize((266 * 3) + 10, (224 * 3) + 10);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class MyFrame extends JFrame {

    MyPanel p;

    public MyFrame() {
        p = new MyPanel();
        add(p);
        setVisible(true);
    }
}

    class MyPanel extends JPanel implements MouseListener {

        public static final int IMAGE_X = 266;
        public static final int IMAGE_Y = 224;
        public static final int PAD = 5;

        private int counter = 0;
        private int previouspicture = -1;
        private int currentpicture = -1;

        private boolean won = false;

        private ArrayList<PicturePiece> images = new ArrayList<PicturePiece>();

        public MyPanel() {

            this.setFocusable(true);

            for (int i = 0; i < 9; i++) {
                images.add(new PicturePiece(i));
            }
            Random rnd = new Random();
            rnd.setSeed(40000);
            Collections.shuffle(images, rnd);
        
            try {
                for (int i = 0; i < images.size(); i++) {
                
                    images.get(i).setImage(new File(("src/chapter/domcek/domcek" + (images.get(i).getId() + 1) + ".jpg")));
                }
            } catch (Exception e) {
            }

            addMouseListener(this);
        
       
        }

        public void draw(Graphics2D g2) {

            int j = 0, k = 0, pocet = 0;
            for (int i = 0; i < 9; i++) {
                images.get(i).draw(g2, j * (IMAGE_X + PAD), k * (IMAGE_Y + PAD));
                pocet++;
                if ((pocet % 3) == 0) {
                    j = 0;
                    k++;
                } else {
                    j = j + 1;
                }
            }
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            validate();
            draw(g2);
            if (won == true) {
                showMessage("You won!!!", g2);
            }
        }

        /**
         * checks whether user clicked on two different pictures and if yes, changes
         * their order
         *
         * @param e - event object
         */
        @Override
        public void mouseClicked(MouseEvent e) {

            int picturepiece_id;

            if (counter == 0) {
                previouspicture = getPicturePiece(e.getX(), e.getY());
                counter = 1;

            } else if (counter == 1) {
                counter = 0;
                currentpicture = getPicturePiece(e.getX(), e.getY());

                if ((previouspicture != currentpicture) && (previouspicture != -1) && (currentpicture != -1)) {
                    swap(previouspicture, currentpicture);

                    repaint();

                    int j = 0;
                    int i = 0;

                    i = 0;
                    while ((j == i) && (i < images.size()) && (j < images.size())) {
                        i++;
                        j = images.get(i).getId();
                        if ((j == 8) && (i == 8)) {
                            won = true;
                            removeMouseListener(this);
                            repaint();

                            break;

                        }

                    }

                }

            }

        }

        /**
         * prints message on winning
         *
         * @param s - message to print
         * @param g2 - graphical context
         */
        public void showMessage(String s, Graphics2D g2) {
            Font myFont = new Font(" SansSerif ", Font.BOLD, 100);
            g2.setFont(myFont);
            g2.setColor(Color.BLUE);
            Rectangle2D textBox = myFont.getStringBounds(s,     g2.getFontRenderContext());
            g2.drawString(s, (int) (getWidth() / 2 - textBox.getWidth() / 2), (int) (getHeight() / 2 - textBox.getHeight()));
        }

        /**
         * returns order number of picture within 3x3 grid where user clicked
         *
         * @param x - X coordinate
         * @param y - Y coordinate
         * @return
         */
        private int getPicturePiece(int x, int y) {

            if ((x <= IMAGE_X) && (y <= IMAGE_Y)) {
                return 0;
            } else if (((x > IMAGE_X) && (x <= IMAGE_X * 2)) && (y <= IMAGE_Y)) {
                return 1;
            } else if (((x > IMAGE_X) && (x <= IMAGE_X * 3)) && (y <= IMAGE_Y)) {
                return 2;
            } else if ((x <= IMAGE_X) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) {
                return 3;
            } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 2))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) {
                return 4;
            } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 3))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) {
                return 5;
            } else if ((x <= IMAGE_X) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) {
                return 6;

            } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 2))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) {
                return 7;

            } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 3))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) {
                return 8;

            } else {
                return -1;
            }
        }

    /**
     * swaps two clicked different pictures
     *
     * @param previouspic - first picture
     * @param currentpic - second picture
     */
        public void swap(int previouspic, int currentpic) {

            int temp = 0;
            int a = previouspic;
            int b = currentpic;
            PicturePiece p = images.get(a);
            PicturePiece p2 = images.get(b);
            images.set(a, p2);
            images.set(b, p);
        }

        @Override
        public void mousePressed(MouseEvent e) {

        }

        @Override
        public void mouseReleased(MouseEvent e) {

        }

        @Override
        public void mouseEntered(MouseEvent e) {

        }

        @Override
        public void mouseExited(MouseEvent e) {

        }
    }
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.