为什么我的BufferedImages没有正确重叠?

时间:2016-04-03 10:59:49

标签: java bufferedimage

我正在尝试编写一个小小的初学者程序,只显示一些BufferedImages,你可以移动并相互叠加。但我无法让屏幕上的图像正确重叠。

我希望用鼠标光标选择的图像是移动的图像,即使鼠标光标位置中存在多个图像也是如此。

这就是我在做的事情;它仅在下方只有1个图像时选择上部图像,因此只有两个图像堆叠时才能工作。但是,如果我有三个图像堆叠或更多共享一个位置,我尝试将图像移到顶部,它选择堆栈底部的图像作为选定的一个移动或只是(似乎)随机任意图像但上部移动。为什么是这样?我希望上面的一个在点击时保持被选中,即使堆叠了很多。

这是我的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;


class Image {

    private int x;
    private int y;
    private BufferedImage front, back;
    private StringBuffer filepath;
    private boolean isTurned;

    public Image(int x, int y, String filepath) throws IOException {
        this.filepath = new StringBuffer(filepath);
        this.x = x;
        this.y = y;
        this.front = ImageIO.read(new File(String.valueOf(filepath)));
        this.back = ImageIO.read(new File(String.valueOf("images/back.gif")));
    }

    public void draw(Graphics g){

        g.drawImage(front, x, y, null);

    }

    public void undraw (Graphics g, Color c ){
        g.setColor(c);
        g.fillRect(x,y, front.getWidth(), front.getHeight());

    }

    public boolean containsXY (int x, int y){

        if ( (this.x <= x ) && (x <= (this.x+this.front.getWidth())) && (this.y <= y ) && (y <= (this.y+this.front.getHeight()))  ){

            return true;
        }

        return false;
    }

    public void move (Graphics g, int x, int y) {

        undraw(g, Color.WHITE);
        this.x = x-(this.front.getWidth()/2);
        this.y = y-(this.front.getHeight()/2);
        draw(g);
    }

    public String getFilePath(){
        return String.valueOf(filepath);
    }

    public int getX(){
        return x;
    }

    public int getY(){
        return y;
    }

    public void turn(Graphics g) throws IOException {

        if (isTurned) {

            undraw(g, Color.WHITE);
            front = ImageIO.read(new File(String.valueOf(filepath)));
            draw(g);
            isTurned = false;
        }

        else {

            undraw(g, Color.WHITE);
            front = back;
            draw(g);
            isTurned = true;
        }
    }

}



class PaintSurface extends JLabel implements MouseListener, MouseMotionListener {

    private int x, y;
    private JButton browse;
    private Collection<Image> images = new ArrayList<Image>();
    private final JFileChooser fc = new JFileChooser();
    private Image selected;
    private boolean drawOnce;
    private Image[] initialImages = new Image[8];

    public PaintSurface(JButton b){
        browse = b;
        addMouseListener(this);
        addMouseMotionListener(this);
        browse.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                int x = fc.showOpenDialog(browse);

                if (x == JFileChooser.APPROVE_OPTION){
                    try {
                        buttonPressed(fc);

                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }

                else if (x ==JFileChooser.CANCEL_OPTION){
                    System.out.println("No file selected.");
                }
            }
        });
    }

    public void paintComponent (Graphics g){
        super.paintComponent(g);

        if (!drawOnce) {
            try {
                drawStartUpImages();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        for (Image i: images){
            i.draw(g);

        }

        drawOnce = true;

    }

    public void drawStartUpImages() throws IOException {

        initialImages[0] = new Image(0, 100, "images/blab.gif");
        initialImages[1] = new Image(100, 100, "images/fred.gif");
        initialImages[2] = new Image(200, 100, "images/gira.gif");
        initialImages[3] = new Image(300, 100, "images/katt.gif");
        initialImages[4] = new Image(0, 300, "images/pear.gif");
        initialImages[5] = new Image(100, 300, "images/peli.gif");
        initialImages[6] = new Image(200, 300, "images/stef.gif");
        initialImages[7] = new Image(300, 300, "images/stru.gif");

        for (int i = 0; i<8; i++) {
            addImage(initialImages[i]);
            repaint();
        }



    }

    public void addImage(Image i){
        images.add(i);

        Graphics g = getGraphics();
        i.draw(g);


    }

    public void buttonPressed(JFileChooser fc) throws IOException {


        File selectedFile = fc.getSelectedFile();
        String filepath = String.valueOf(selectedFile.getAbsolutePath());
        Image i = new Image(x, y, filepath );
        selected = i;
        addImage(i);


        repaint();

    }

    public Image findImage(int x, int y){

        for (Image i: images){
            if (i.containsXY(x, y)){
                return i;

            }

        }
        return null;
    }

    public void moveImage (Image i, int x, int y) { //

        i.move(getGraphics(), x, y);
    }

    public boolean removeImage(Image i){

        Graphics g = getGraphics();
        i.undraw(g, Color.WHITE);

        return images.remove(i);

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        //selected = findImage(e.getX(), e.getY());

        if (selected != null && findImage(x,y) == selected) {

            Graphics g = getGraphics();
            try {
                selected.turn(g);
            } catch (IOException e1) {
                e1.printStackTrace();
            }

        }

    }

    @Override
    public void mousePressed(MouseEvent e) {

        if (findImage(e.getX(), e.getY()) != null){
            selected = findImage(e.getX(), e.getY());
        }

        if ( (findImage(e.getX(), e.getY()) != null && findImage(e.getX(), e.getY()) == selected) ){

            removeImage(selected);
            addImage(selected);

        }

        if ((findImage(e.getX(), e.getY()) != null && findImage(e.getX(), e.getY()) != selected)) {


            try {
                selected = new Image(findImage(e.getX(), e.getY()).getX(), findImage(e.getX(), e.getY()).getY(), findImage(e.getX(), e.getY()).getFilePath());
                removeImage(findImage(e.getX(), e.getY()));
                addImage(selected);

            } catch (IOException e1) {
                e1.printStackTrace();
            }

        }


    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        if (selected != null) {
            moveImage(selected,x,y);
            repaint();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }
}
class GUI extends JFrame {

    public GUI(){
        super("ImageApp");

        JLabel instruction = new JLabel("Clicking on the screen will set the location for the next added image.");
        JButton browse = new JButton("Add image");
        JButton line = new JButton("Line up");
        JPanel panel1 = new JPanel();
        JLabel panel2 = new PaintSurface(browse);
        panel1.setLayout(null);
        panel2.setBackground(Color.WHITE);
        instruction.setAlignmentX(CENTER_ALIGNMENT);

        getContentPane().setBackground(Color.WHITE);
        getContentPane().add("North", instruction);
        getContentPane().add("South", browse);

        add(panel2);
        setBounds(300,0,800,800);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

    }





}


public class PhotoApp extends GUI {

    public static void main (String[] args){
        GUI PhotoApplication = new GUI();
    }
}

请原谅我,如果这段代码不好,我只是想让重叠正常工作。我认为问题出现在PaintSurface类中,在Mouselistener函数MousePressed和MouseDragged中。我已经尝试了很多,但我似乎无法让它继续选择上面的图像,当其他几个图像,我点击顶部的图像。它选择一个下面并重绘为最顶层。就像我说的那样,当只有两个图像堆叠在一起时,它才起作用,只有当我点击时才会选择下面的图像。有谁知道我如何让重叠正常工作?

1 个答案:

答案 0 :(得分:0)

问题是,您findImage()方法始终会返回ArrayList中的第一个匹配项。

mousePressed()方法中,您首先将selected设置为findImage(),然后再检查selected == findImage()是否始终为真。 然后,您从ArrayList中移除图片并在结尾处再次添加, 因此,如果此位置有多个图像,则下一个if子句将始终存在 是的,因为您已经选择了图片现在已经结束了,findImage()将在此位置返回另一张图片。

首先你可以这样做:

if (findImage(e.getX(), e.getY()) == null) { return; }

mousePressed的开头,因为它出现在每个if子句中。

之后你就能做到这样的事情:

if (findImage(e.getX(), e.getY()) == selected) ){ [...] } else { [...] }

所以现在只有一个原始的if子句会被执行。

希望通过这个小小的帮助,你能够解决问题。