繁体   English   中英

Java drawImage方法

[英]Java drawImage method

我正在尝试在练习中将一组Picture对象放入ArrayList中,然后随机将它们随机播放,并将它们显示为3x3的网格。 但是,随机播放方法对我来说无法正常工作。 也许我不知道我在draw或drawImage方法中做错了什么。 我总是按原始顺序显示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;
    }
}

这是我的主要课程:

/ *从Internet查找漂亮的图像,然后使用图像编辑器将其分解为9个部分(例如,您可以在Windows中使用应用程序Paint)。 在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);      
    }
}

由于您正在MyPanel函数中设置行/列(j和k),因此会出现错误。

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

为了实现该行为,您希望我从列表中的顺序生成行/列。

问题是您基于初始坐标绘制图像 ,即使您将它们拖拉,其坐标在PicturePiece对象中也保持不变。

简短的解决方案:

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矩阵),但我希望您有想法。 还有许多其他解决方案,但这是我能想到的最短的解决方案。

与其使用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;
    }
}

OUTPUT:

初始FINALOUTPUT

CMDOUTPUT

使用的图像:

  1. 原始图像: http //i.imgur.com/GNIZRQy.jpg
  2. 对于SPLIT,我使用了以下站点: http : //imagesplitter.net/

首先,让我感谢您的时间和精力。 我以这种方式编写了应用程序/实验室:

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);
}

}

类MyFrame扩展了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) {

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM