GUI Making Arrays of Images that Move Using Mouse Event

不打扰是莪最后的温柔 提交于 2019-12-11 07:47:09

问题


I am pretty overwhelmed at the moment with this assignment. I am only 3 weeks into Java programming and I was given this code and told to modify it in ways I'm not exactly familiar with. So any help would be greatly appreciated. I really want to understand this, so any information would also be helpful.

The directions that I'm struggling with at the moment are:

"Modify the Model class to store an ArrayList of Turtles. Make Model.update call Turtle.update for each Turtle in the ArrayList. To test it, put two or three turtles in the ArrayList, each starting in different locations. When you click (which causes "setDestination" to be called), make all of the turtles head for the same destination. Get this much working before you proceed."

Before I created an array of these turtles, one turtle showed up fine. Now that I have created an array, nothing is showing up on my panel. It does compile properly, though. I understand that I should make separate Graphics objects, but how and where would be the best place to do this? Here is the code (which was in 4 separate files):

Controller.java

import java.awt.Graphics;
import java.io.IOException;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.Timer;

class Controller implements MouseListener
{
    Model model;
    View view;

    Controller() throws IOException, Exception {
        model = new Model();
        view = new View(this);
        new Timer(50, view).start();
    }

    public void update(Graphics g) {
        model.update(g);
    }

    public void mousePressed(MouseEvent e) {
        model.setDestination(e.getX(), e.getY(), view.getWidth(), view.getHeight());
    }

    public void mouseReleased(MouseEvent e) {    }
    public void mouseEntered(MouseEvent e) {    }
    public void mouseExited(MouseEvent e) {    }
    public void mouseClicked(MouseEvent e) {    }

    public static void main(String[] args) throws Exception {
        //  Use the following line to determine which directory your program
        //  is being executed from, since that is where the image files will
        //  need to be.
        //System.out.println("cwd=" + System.getProperty("user.dir"));
        new Controller();
    }
}

Model.java

import java.awt.Graphics;
import java.io.IOException;

class Model
{
    private Turtle[] t;

    Model() throws IOException {
        Turtle[] t = new  Turtle[3];    
            for (int i = 0; i <3; i++)
             t[i] = new Turtle();

       // turtle = new Turtle();
    }

    public void update(Graphics g) {         
        for(int i = 0; i <3; i++)
            t[i].update(g);             
    }

    public void setDestination(int x, int y, int width, int height) {
        for(int i = 0; i <3; i++)
        { 
            t[i].setDest(x, y);
        }    
    }    
}

Turtle.java

import java.awt.Graphics;
import java.awt.Image;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.Random;

class Turtle
{
    private int x;
    private int y;
    private int dest_x;
    private int dest_y;
    private Image image;

    Turtle() {
        try {
            image = ImageIO.read(new File("turtle.png"));
        } catch (IOException ioe) {
            System.out.println("Unable to load image file.");                
        }            
    }

    public int getX() { return x; }
    public int getY() { return y; }

    public void setX(int xIn) { x = xIn; }
    public void setY(int yIn) { y = yIn; }

    public void update(Graphics g) {
        // Move the turtle
        if (x < dest_x) {
            x += 1;
        } else if (x > dest_x) {
            x -= 1;
        }

        if (y < dest_y) {
            y += 1;
        } else if (y > dest_y) {
            y -= 1;
        }

        // Draw the turtle                     
    }

    public void setDest(int x, int y) {
        dest_x = x;
        dest_y = y;
    }
}

View.java

import javax.swing.JFrame;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class View extends JFrame implements ActionListener {

    private class MyPanel extends JPanel {
        Controller controller;

        MyPanel(Controller c) {
            controller = c;
            addMouseListener(c);
        }

        public void paintComponent(Graphics g) {
            controller.update(g);
            revalidate();
        }
    }


    public View(Controller c) throws Exception{
        setTitle("Assignment 4");
        setSize(1000, 700);
        getContentPane().add(new MyPanel(c));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent evt) {
        repaint();
    }
}

回答1:


I'm positively surprised by the code supplied by the teacher; usually it's pretty bad, but this one is decent. Although you need to modify only one class, allow me to comment a bit more because "any information would also be helpful".

Controller

class Controller extends MouseAdapter

instead of

class Controller implements MouseListener

allows you to get rid of all the empty methods

public void mouseReleased(MouseEvent e) {    }
public void mouseEntered(MouseEvent e) {    }
public void mouseExited(MouseEvent e) {    }
public void mouseClicked(MouseEvent e) {    }

(And in case you need to extend controller with something else just make an inner class extending MouseAdapter and use that.)

Turtle

Should expose a constructor such as

Turtle(int x, int y) {

    this();
    this.x = x;
    this.y = y;
}

so that

Turtle t = new Turtle();
t.setX(4);
t.setY(6);

could be replaced with

new Turtle(4, 6);

Furthermore, dest_x and dest_y should be renamed to something like destX and destY since underscore (_) is used only in names of final instances.

Lastly, you need to replace the line

// Draw the turtle

with

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

View

The dimensions specified in

setSize(1000, 700);

should be defined as fields (don't scatter arbitrary numbers across the code)

int sizeX = 1000, sizeY = 700;
...
setSize(sizeX, sizeY);

and should be exposed so that when choosing initial location for the turtles they won't start out of bounds.

Model

You were asked: Modify the Model class to store an ArrayList of Turtles, but you created an array instead for some reason. Here is an example of what you can do to make it work:

public class Model {

    private List<Turtle> turtList = new ArrayList<>();
    private int turtleNumber = 3;

    Model() throws IOException {

        for (int i = 0; i < turtleNumber; i++) {
            Turtle turt = new Turtle();
            turt.setX(Math.round((float)Math.random() * 1000));
            turt.setY(Math.round((float)Math.random() * 700));
            turtList.add(turt);
        }
    }

    public void update(Graphics g) {

        for (int i = 0; i < turtleNumber; i++)
            turtList.get(i).update(g);
    }

    public void setDestination(int x, int y, int width, int height) {

        for (Turtle turt : turtList)
            turt.setDest(x, y);
    }
}

I define the number of turtles I want as a field and use it throughout the code so I need to change it only in one place when I change the number.

In the constructor, I loop using the given turtle constructor (a null constructor) and randomly place them inside the frame's bounds (they should be read from View's sizeX and sizeY). Then I add the modified turtle to the list.

For instructional purpose, I used two different looping constructs for update and for setDestination. Choose whichever you want (just notice that you don't need to know the number of turtles).




回答2:


In the constructor of your Model class you have the line

Turtle[] t = new  Turtle[3];

You also have the class variable,

Turtle[] t

but are not assigning the array initialised in the Constructor to the class variable, so it is only considered for the scope of that method and hence why nothing is drawn, as when you go to use the variable t later it has not been initialised and so you get NullPointerExceptions

To fix this simply change the line

Turtle[] t = new  Turtle[3];

to

t = new  Turtle[3];

Now this will only appear as one image, but is actually 3 turtles overlaid on top of each other. So to fix this you will need some extra code to put the turtles in different starting positions, but i'll leave you to figure this part out.



来源:https://stackoverflow.com/questions/26049313/gui-making-arrays-of-images-that-move-using-mouse-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!