我正在尝试编写一个小小的初学者程序,只显示一些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中。我已经尝试了很多,但我似乎无法让它继续选择上面的图像,当其他几个图像,我点击顶部的图像。它选择一个下面并重绘为最顶层。就像我说的那样,当只有两个图像堆叠在一起时,它才起作用,只有当我点击时才会选择下面的图像。有谁知道我如何让重叠正常工作?
答案 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子句会被执行。
希望通过这个小小的帮助,你能够解决问题。