首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java drawImage方法

Java drawImage方法
EN

Stack Overflow用户
提问于 2015-03-02 20:02:55
回答 4查看 2.6K关注 0票数 2

我在练习中尝试将一组图片对象放到ArrayList中,然后随机地对它们进行洗牌,并将它们显示为一个3x3的网格。但是,shuffle方法对我来说不能正常工作。或者也许我在draw或drawImage方法中做错了什么,我不知道。我总是得到图片显示从9件在他们的原始顺序,而不是随机洗牌。

请看下面我的PicturePiece类以及主类。

代码语言:javascript
复制
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中使用应用程序Paint )。在3×3网格中以随机顺序显示9个图像。添加鼠标侦听器。允许用户通过单击来交换两个图像。游戏的目标是重新创建原始图像。当用户获胜时显示相应的消息。*/

代码语言:javascript
复制
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);      
    }
}
EN

回答 4

Stack Overflow用户

发布于 2015-03-02 20:47:48

票数 1
EN

Stack Overflow用户

发布于 2015-03-02 20:55:58

问题是,您基于初始化坐标绘制图像,即使您将它们置乱,PicturePiece对象中的坐标也保持不变。

简短的解决方案:

PicturePiece中的更改:

代码语言:javascript
复制
public void draw(Graphics2D g2, int i, int j) {
    g2.drawImage(this.img, this.IMAGE_X *i, this.IMAGE_Y * j, null);
}

拼图中的变化:

代码语言:javascript
复制
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矩阵),但我希望你得到了ideea。有许多其他的解决方案,但这是我能想到的最短的一个。

票数 1
EN

Stack Overflow用户

发布于 2015-03-02 22:20:04

明智的做法是使用JLabel,而不是在JPanel/JComponent上绘制,这将使您的工作变得更容易,因为您只需关心索引位置。

这里有一个例子:

代码语言:javascript
复制
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;
    }
}

输出:

使用的图像:

  1. ORIGINAL图片:http://i.imgur.com/GNIZRQy.jpg
  2. To SPLIT,我使用了这个网站:http://imagesplitter.net/
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28809341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档