问题
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