BUG Community

Welcome! Log In

Forums Java Graphics Question

Subscribe to Graphics Question  14 posts, 3 voices

Log in to reply to this topic
 
Mar 16, 2008 9:50pm
Img_missing_medium amormachine 6 posts

Hi,

I’m trying to learn Java in preparation for getting a Bug and have gotten stuck when it comes to understanding how graphics work.

I wrote a program that randomly selects a start and ending point on a 2D grid. Then, it unleashes thousands of ‘bugs’ (cast from the bug class) which move about quasi-randomly trying to find the end point.

Basically, I’d like to simply be able to draw out that 2D grid and illustrate each bug as a colored circle. Could someone explain how that could be done in my code, or point to a sample program which does something similiar?

Thanks!

CLASS 1:
public class Bug {

/ Initial Variables /
        String name;
        private int xPos;            //X-Position variable
        private int yPos;            //Y-Position variable
        private int i = 0;            //Indexing Variable
        private float xPosRandom = (float) Math.random();
        private float yPosRandom = (float) Math.random();
/ This method is used to pull in the initial starting position of the given
        Bug object /
        public void setInitialize(BugMain2 HiveMind)    {
// Pull Initial Starting Coordinates
        xPos = HiveMind.getxStartPosition();
        yPos = HiveMind.getxStartPosition();
}
/ This method is used to randomly simulate movement used to simulate movement /
        public void moveBug(BugMain2 HiveMind)    {
// Modification of the X-Position Variable
        if (Math.random() >= xPosRandom)    {
            ++xPos;
        }    else    {
            --xPos;
        }
// Modification of the Y-Position Variable
        if (Math.random() >= yPosRandom)    {
            ++yPos;
        }    else    {
            --yPos;
        }
// Final Checks for Arena Size Constraints (i.e. the bug can't leave the field)
        if (xPos > HiveMind.getxMaxValue())    {    --xPos;        }
        if (yPos > HiveMind.getyMaxValue())    {    --yPos;        }
if (xPos < HiveMind.getxMinValue())    {    ++xPos;        }
        if (yPos < HiveMind.getyMinValue())    {    ++yPos;        }
System.out.println(name  ": "  i  " "  getxPos()  " "  getyPos());
        i++;
if (xPos  HiveMind.getxEndPosition() && yPos  HiveMind.getyEndPosition())    {
            HiveMind.setIsFinished(true);
            System.out.println("");
            System.out.println("Solution Found By: " + name);
            System.out.println("Number of Attempts: " + i);
            System.out.println("Percent Over Optimal: " + (float) 100  Math.abs(Math.max(HiveMind.getxEndPosition(), HiveMind.getyEndPosition()) - i)/Math.max(HiveMind.getxEndPosition(), HiveMind.getyEndPosition()));
        }
}
/ Used to get the xPos variable /
        public int getxPos()    {
            return xPos;
        }
/ Used to get the yPos variable /
        public int getyPos()    {
            return yPos;
        }
/ Used to set the Bug's Name /
        public void setName(String nameString)    {
            name = nameString;
        }

}

CLASS 2:
import javax.swing.
;
import java.awt.;
import java.awt.geom.
;

public class BugMain2 {

/ Initialization of Important Parameters /
        int xStartPosition = 0;            //Initialization of starting positions
        int yStartPosition = 0;
int xEndPosition = 87;            //Initialization of ending position (puzzle solution)
        int yEndPosition = 66;
int xMaxValue = 100;            //Initialization of max and min values for the arena
        int yMaxValue = 100;
        int xMinValue = 0;
        int yMinValue = 0;
int NumberInSwarm = 1000;
Boolean IsFinished = false;
public static void main(String[] args)    {
// Variables and Objects
        BugMain2 HiveMind = new BugMain2();
        HiveMind.go(HiveMind);
}
public void go(BugMain2 HiveMind)    {
// Creation of Bug(s)
        Bug[] Bugs = new Bug[NumberInSwarm];
// Initialization
        for (int i=0; i < NumberInSwarm; i++)    {
            Bugs[i] = new Bug();
            Bugs[i].setName("BuG_" + i);
        }
// Begin Race
        while (IsFinished != true)    {
for (int j=0; j < NumberInSwarm ; j++)    {
            Bugs[j].moveBug(HiveMind);
            if (IsFinished == true)    {    break;    }
}
}
}
public int getxStartPosition()    {
            return xStartPosition;
        }
public int getyStartPosition()    {
            return yStartPosition;
        }
public int getxEndPosition()    {
            return xEndPosition;
        }
public int getyEndPosition()    {
            return yEndPosition;
        }
        public int getxMaxValue()    {
            return xMaxValue;
        }
public int getyMaxValue()    {
            return yMaxValue;
        }
public int getxMinValue()    {
            return xMinValue;
        }
public int getyMinValue()    {
            return yMinValue;
        }
public void setIsFinished(Boolean IsFound)    {
            IsFinished = IsFound;
        }

}

Mar 17, 2008 12:44pm
Medium Bug Labs team kschultz 107 posts

Hey,

I definately want to get back to you on this question although I am leaving for class in 5 minutes so here is the 10 second answer.

1) Check out the java.awt.Canvas and java.awt.Graphics2D classes
2) You can’t use javax.swing stuff, that is not available on the BUG, only the java.awt.*; classes are

Searching my del.icio.us I came up with these, don’t know if they helpful but at some point in time I tagged them with AWT and Java

http://java.sun.com/developer/onlineTraining/aw…
http://home.cogeco.ca/ve3ll/jatutorg.htm
http://www.javaworld.com/javaworld/jw-07-1996/j…

Longer answer later!

Mar 17, 2008 3:58pm
Img_missing_medium amormachine 6 posts

Thanks for the quick reply, I’m definitely looking forward to your next one!

I still am confused about the graphics class (probably because I am so new to this), so forgive the dumb question, but are there graphics objects? All examples seem to show a method accepting a graphics object as an input, but I never see where it is instantiated, or even what java libraries are needed. If you could, in your next response, could you shed some light on that?

Thanks!

Mar 25, 2008 9:40pm
Img_missing_medium amormachine 6 posts

If you get a chance, can you post some sample code / point to a tutorial?

Thanks!

Mar 25, 2008 11:23pm
Medium Bug Labs team kschultz 107 posts

Yea I definitely will I didn’t mean to leave you hanging but I’m in the middle of midterms this week (4 midterms 20 page paper a lot of regular homework = no time). Next week I will get a chance since I am on spring break, sorry for the wait.

Mar 25, 2008 11:38pm
Img_missing_medium amormachine 6 posts

No problem at all! Good luck with the tests!

Mar 31, 2008 11:27pm
Medium Bug Labs team kschultz 107 posts

Hey,

I started working on an example for you. Got the static graphics going, the animation part is going to be harder. Do you want the BUG's location to update or just show the first time the app is launched statically? If you want them statically then just make a new class like the gridmarker one, but I had assumed you wanted it to update which is a bit more involved. I'll be working on that tomorrow.

Here is what it looks like at the moment:



And here is the code, the first two classes are the same as they would be for the bug, the last just the Frame to test stuff out


The canvas that you can draw on

import java.awt.Canvas;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Color;

public class ExampleCanvas extends Canvas {

public ExampleCanvas(Frame f) {
this.setBackground(Color.WHITE);
this.setSize(310, 210);

}

public void paint(Graphics g) {
for(int x = 0; x < 320; x+=25) {
for(int y = 0; y< 240; y +=25) {
new GridMarker(x,y,g);
}
}

}
}



This is the class for the little markers


package canvastest.app;

import java.awt.Graphics;
import java.awt.Color;

public class GridMarker {

private final int width = 7;
private final int height = 7;
private int x;
private int y;

public GridMarker(int x, int y, Graphics g) {
this.x = x;
this.y = y;
paint(g);
}

public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.drawLine(x-width/2, y, x+width/2, y);
g.drawLine(x, y-height/2, x, y+height/2);
}
}


The main class, this would be your app that gets called from the servicetracker on the BUG, I am just doing it as a vanilla Java app
for no particular reason


package canvastest.app;

import java.awt.Frame;
import canvastest.app.ExampleCanvas;

public class CanvasTestMain {

/**
* @param args
*/
public static void main(String[] args) {
createUI();
}

private static void createUI() {
Frame frame = new Frame("CanvasTest");
frame.setSize(320, 240);
frame.setResizable(false);

ExampleCanvas canvas = new ExampleCanvas(frame);

frame.add(canvas);

frame.show();
}

}
Apr 1, 2008 9:59pm
Img_missing_medium amormachine 6 posts

Thanks for the sample code!

I’ve got it up and running and have been playing around with it for a bit now. FYI: Eclipse didn’t like a few lines like involving packaging and importing, so I commented them out.

I have two quick questions for you though …

1. When I run the code in Eclipse, the frame pops up as it should … However, when I try to x-it out, it wont go away. I’ve had to resort to Ctrl-Alt-Delete. Why is that?

2. I can’t seem to figure out how the paint method it ExampleCanvas is being called! I’ve looked everywhere, but I never see it called, not even in the constructors … I must be missing something simple, what is it??

Thanks again!

Apr 1, 2008 10:11pm
Medium Bug Labs team kschultz 107 posts

The paint method in ExampleCanvas gets called with the frame.show(); line in the main method. Every component that you add to a container gets its paint method called then. Even though Eclipse likes to cross that line out as depreciated, it is not and you need that line.

As for stopping the window, not sure, but if you hit the red square on the console in Eclipse it will close easily.

The packaging depends on how you setup your project. I like to make things broken up into a lot of packages because I like to reuse my code as much as possible, I’d rather write twice as much if I can use it again because no matter how one off a project I think it is, I always seem to use some of it later.

Apr 1, 2008 10:19pm
Medium Bug Labs team kschultz 107 posts

Here is a good reference on the paint method and updating in AWT. I’m working on casting a bunch of BUGs around the screen and updating them.

http://java.sun.com/products/jfc/tsc/articles/p…

I have to say that my example is not exactly their perfect use case, but I’m working on it. They say that you should not call the paint class explicitly for a number of reasons (basically, it can fail) and use the repaint() method. That brings up the point of breaking up what you are drawing into objects. It would be tempting to just throw it all in as one Canvas object that needs to get drawn, but then each time it needs to be updated, everything needs to be redrawn. If you make it a number of objects then only the updated objects need to be repainted which hopefully will reduce flicker. Now I’m thinking should each BUG be an object or should I make an object that paints all of them like I did for the gridmarkers? If they are all to be updated every time, then one object is the best route for minimum overhead, but if only some are going to be updated each time than making each one an object would be better. That is kind of up to you.

Apr 2, 2008 6:19am
Medium Bug Labs team jconnolly 285 posts

amormachine
Thanks for the sample code!

I've got it up and running and have been playing around with it for a bit now. FYI: Eclipse didn't like a few lines like involving packaging and importing, so I commented them out.

I have two quick questions for you though ...

1. When I run the code in Eclipse, the frame pops up as it should ... However, when I try to x-it out, it wont go away. I've had to resort to Ctrl-Alt-Delete. Why is that?

2. I can't seem to figure out how the paint method it ExampleCanvas is being called! I've looked everywhere, but I never see it called, not even in the constructors ... I must be missing something simple, what is it??

Thanks again!


Amormachine,

You raise a good point about responsible AWT and OSGi bundle programming. If by closing the Frame you mean to terminate the application, you must express this programmatically. The default behavior of a Frame object when closed is to do nothing. To change this, you must override and flesh out the relevant methods from the WindowAdapter interface. Picking up on Kevin's code, here is what that would look like:


package canvastest.app;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import canvastest.app.ExampleCanvas;

public class CanvasTestMain {

/**
* @param args
*/
public static void main(String[] args) {
createUI();
}

private static void createUI() {
Frame frame = new Frame("CanvasTest");
frame.setSize(320, 240);
frame.setResizable(false);

ExampleCanvas canvas = new ExampleCanvas(frame);

frame.add(canvas);

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {

frame.dispose();
//do some happy ungetting of services
//and other tidying up here, before exiting.
}
});


frame.show();
}

}



For more information about WindowListener, WindowEvent, WindowAdapter see some code samples here:

http://www.exampledepot.com/egs/java.awt/pkg.html


The code addition above uses anonymous inner classing, which can be very convenient for GUI programming. Instead of laboriously defining classes that extend the abstract classes and override the relevant methods, or worse, implementing an interface and overriding all the methods for each event handler (MouseListener, MouseMotionListener, etc), you may define it right within the declaration itself. This practice is very common in GUI programming. Most GUI Builders do this in code generation too.

See a nice lecture at Stanford (PDF) for a pretty decent overview of anonymous inner classing in Java:

www.stanford.edu/class/cs108/handouts061/17AnonymousInner.pdf

I should also note that calling System.exit(0) from within any Bundle is bad news! This makes a system call which in turn terminates the entire VM process on the host OS. While this may be ok for the Virtual BUG, this would be very unkind to the other OSGi bundles running concurrently with your own.

Lastly, it may be best not to hard-code the Frame size in your application. Not all LCD resolutions are the same, there is an LCD module in the pipes that would stretch nearly the entire width of the physical BUG!

Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setSize((int)d.getWidth(). (int)d.getHeight());


I'm working on setting up a Wiki for Java tips and suggestions for BUG coders. I'll be sure to announce when it's up.
Apr 2, 2008 10:04am
Medium Bug Labs team kschultz 107 posts

Thanks John,

I am far from an authority on AWT, my GUI programming was all Qt/C+ and GTK/C++ prior to the BUG, but Sun has a lot of good reference material, if only I took the time to read it!

Apr 2, 2008 10:28am
Medium Bug Labs team jconnolly 285 posts

kschultz
Thanks John,

I am far from an authority on AWT, my GUI programming was all Qt/C++ and GTK+/C++ prior to the BUG, but Sun has a lot of good reference material, if only I took the time to read it!


Kschultz,

Your apps are great! With the physical BUG now available, it's important to ensure as much contunity in behavior between the Virtual BUG and physical BUG. Sometimes I wish there was a red "terminate application" square somewhere on the physical BUG. :wink:

I've put up a sample application for how to use Anonymous Inner Classes and WindowAdapter/Listener, MouseAdapter/Listeners on BugNet for reference.
Apr 2, 2008 1:39pm
Medium Bug Labs team kschultz 107 posts