java - Painting a Runnable JPanel -
i working on little horse race simulator , stuck it. want user first select number of horses in race (2-6) , click on "start" button. then, want draw/paint race track , horses (represented circles). reason, when code reaches point of creating instance of horse, never gets drawn frame. below code. missing?
main.java:
import javax.swing.swingutilities; public class main { public static void main(string[] args) { swingutilities.invokelater(new runnable() { @override public void run() { racetrack myrace = new racetrack(); myrace.setvisible(true); } }); } }
racetrack.java:
import java.awt.borderlayout; import java.awt.container; import java.awt.event.actionevent; import java.awt.event.actionlistener; import javax.swing.borderfactory; import javax.swing.buttongroup; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.jpanel; import javax.swing.jradiobutton; import javax.swing.border.border; public class racetrack extends jframe implements runnable { public racetrack() { initui(); } public static int selectedracesize = 2; private void initui() { final container pane = getcontentpane(); string horsenum[] = { "2", "3", "4", "5", "6" }; jpanel buttonpanel = new jpanel(); border border = borderfactory.createtitledborder("please select number of horses:"); buttonpanel.setborder(border); buttongroup buttongroup = new buttongroup(); jradiobutton aradiobutton; // each string passed in: // create button, add panel, , add group (int = 0, n = horsenum.length; < n; i++) { if (i == 0) { // default selection aradiobutton = new jradiobutton(horsenum[i], true); } else { aradiobutton = new jradiobutton(horsenum[i]); } buttonpanel.add(aradiobutton); buttongroup.add(aradiobutton); } pane.add(buttonpanel, borderlayout.page_start); final jpanel racetrackpanel = new jpanel(null); final jbutton startbutton = new jbutton("start!"); startbutton.addactionlistener(new actionlistener() { public void actionperformed(actionevent actionevent) { startbutton.setenabled(false); horse horse1 = new horse("horse1"); racetrackpanel.add(horse1); pane.add(racetrackpanel, borderlayout.center); repaint(); } }); pane.add(startbutton, borderlayout.page_end); startbutton.setbounds(50, 200, 300, 30); settitle("horse race v1.0"); setsize(400, 300); setresizable(false); setlocationrelativeto(null); setdefaultcloseoperation(exit_on_close); } @override public void run() { try { thread.sleep(50); } catch (interruptedexception e) { e.printstacktrace(); } repaint(); } }
horse.java:
import java.awt.color; import java.awt.graphics; import java.awt.graphics2d; import javax.swing.jpanel; @suppresswarnings("serial") public class horse extends jpanel implements runnable { thread runner; public horse() { } public horse(string threadname) { runner = new thread(this, threadname); runner.start(); } public void run() { this.repaint(); } @override public void paintcomponent(graphics g) { super.paintcomponent(g); graphics2d g2d = (graphics2d) g; g2d.setcolor(new color(252, 211, 61)); g2d.drawoval(20, 25, 10, 10); g2d.filloval(20, 25, 10, 10); } }
what missing?
you're missing data model. you're trying in view.
the view displaying data model.
your horse class should more this:
import java.awt.color; import java.awt.graphics; import java.awt.point; import java.util.random; public class horse { public static final int radius = 15; public static final int margin = 15; public static final int diameter = radius + radius; public static final int position = diameter + margin; private static point currentposition; static { int x = margin + radius; int y = margin + radius; currentposition = new point(x, y); } private static random random = new random(); /** distance in pixels */ private double distance; /** velocity in pixels per second */ private int velocity; private color color; /** initial position in pixels */ private point initialposition; private string name; public horse(color color, string name) { setinitialposition(); this.color = color; this.name = name; init(); } private void setinitialposition() { this.initialposition = new point(currentposition.x, currentposition.y); currentposition.y += position; } public void init() { this.distance = 0.0d; } public void setvelocity() { this.velocity = random.nextint(5) + 6; } public double getdistance() { return distance; } public string getname() { return name; } public void movehorse(int milliseconds) { double pixels = 0.001d * velocity * milliseconds; this.distance += pixels; } public void draw(graphics g) { g.setcolor(color); g.filloval(initialposition.x + (int) math.round(distance) - radius, initialposition.y - radius, diameter, diameter); } }
the last method in class draw. when creating animation, it's lot easier if objects draw themselves.
here's race class.
import java.awt.color; import java.awt.graphics; import java.util.arraylist; import java.util.list; public class race { /** distance of race in pixels */ private double distance; private long elapsedtime; private list<horse> horses; public race(double distance) { this.distance = distance; this.horses = new arraylist<horse>(); this.elapsedtime = 0; } public void init() { this.elapsedtime = 0; (horse horse : horses) { horse.init(); } } public void addhorse(horse horse) { this.horses.add(horse); } public int gethorsecount() { return horses.size(); } public double getdistance() { return distance; } public void setelapsedtime(long elapsedtime) { if (iswinner() == null) { this.elapsedtime = elapsedtime; } } public string getelapsedtime() { int centiseconds = (int) (((elapsedtime % 1000l) + 5l) / 10l); int seconds = (int) (elapsedtime / 1000l); if (seconds < 60) { return string.format("%2d.%02d", seconds, centiseconds); } else { int minutes = seconds / 60; seconds -= minutes * 60; return string.format("%2d:%02d.%02d", minutes, seconds, centiseconds); } } public int gettrackwidth() { return (int) math.round(getdistance()) + 100; } public int gettrackheight() { return gethorsecount() * horse.position + horse.margin; } public void sethorsevelocity() { (horse horse : horses) { horse.setvelocity(); } } public void updatehorsepositions(int milliseconds) { (horse horse : horses) { horse.movehorse(milliseconds); } } public horse iswinner() { (horse horse : horses) { if ((distance - horse.radius) <= horse.getdistance()) { return horse; } } return null; } public boolean allhorsesrunning() { (horse horse : horses) { if ((distance + horse.radius + 6) > horse.getdistance()) { return true; } } return false; } public void draw(graphics g) { drawline(g, horse.position, 6); drawline(g, (int) math.round(getdistance()) + horse.radius + horse.margin, 6); (horse horse : horses) { horse.draw(g); } } private void drawline(graphics g, int x, int width) { int y = horse.margin; int height = gethorsecount() * horse.position - y; g.setcolor(color.black); g.fillrect(x, y, width, height); } }
again, draw method draws race.
so, jpanel draw on like?
import java.awt.color; import java.awt.dimension; import java.awt.graphics; import javax.swing.jpanel; import com.ggl.horse.race.model.race; public class racepanel extends jpanel { private static final long serialversionuid = 1040577191811714944l; private race race; public racepanel(race race) { this.race = race; int width = race.gettrackwidth(); int height = race.gettrackheight(); this.setpreferredsize(new dimension(width, height)); } @override protected void paintcomponent(graphics g) { super.paintcomponent(g); drawbackground(g); race.draw(g); } private void drawbackground(graphics g) { g.setcolor(color.white); g.fillrect(0, 0, getwidth(), getheight()); } }
the view doesn't care if there's 1 horse, 3 horses, or 10 horses. view doesn't change.
only model changes.
this should enough information started.
Comments
Post a Comment