Graphics2D reset Screen? - java

I have a Game Tutorial that I followed, that paints String's on the Screen using Graphics2D. It works like a star, but the only problem is that I don't undertstand why.
I call draw(graphics) in a game loop and it works fine. I use an int, named currentChoice to keep track of which letter should be Red and which should be Black.
Well, I call the method Draw in a loop. I just don't understand how does the graphics clear the previous string it drew. I mean, I call the method constantly, and it keeps on Drawing string's on the window, and its 'clearing' the other ones (if you get what i'm saying).
Basicly, I just don't undertstant how it's clearing the screen (NOTE: I am super new to this sort of thing)
CODE (I call this in a loop and it works):
public void draw(Graphics2D graphics) {
bg.draw(graphics);
graphics.setColor(titleColor);
graphics.setFont(titleFont);
graphics.drawString("Peache's Revenge", 50, 70);
graphics.setFont(font);
for (int i = 0; i < options.length; i++) {
if (i == currentChoice) {
graphics.setColor(Color.RED);
} else {
graphics.setColor(Color.BLACK);
}
graphics.drawString(options[i], 145, 140 + i * 15);
}
}

Assuming the Graphics context does not change (ie is the same for each call), then, unless the background is cleared, content will continue to be painted ontop of it.
From you comments, bg.draw is drawing the background, over the top of whatever was previously painted, meaning that anything that was previously painted will now be covered by the background, thus requiring the text to be re-generated.

Related

How to make buttons on Java Swing Application when constantly redrawing frames

The simple version is that I'm drawing Graphics2D 60 times a second on a JPanel and it uses the drawstring method to create a bunch of labels. How would I go about making so I can click on those labels and have something happen?
Explanation: As it currently stands I have a system setup that says for every object in the world draw a string to the side (So I can see a list of all objects in the world). This is done with a for loop and the Graphics2D drawstring method.
The JPanel is being updated 60 times a second so this is being redrawn 60 times a second. I want to be able to click on these object labels so I can select the items, how would I go about turning them into buttons?
I messed around with JButton for awhile but it didn't seem to do me any good because whenever I added it the JPanel would go blank and only the button would render (Plus it didn't render to the right size).
More Details:
I use a
for(int I=0; I < sceneObjects.size(); I++) {
}
loop to grab every object in an object ArrayList. Each object has a String variable "Name". Before the loop class I sent an int called YPosition, and for every object the YPosition goes up by 20 so that the labels don't all stack on top of each other. I'm using the g2d.DrawString method to achieve this. But I need to be able to select the object labels.
I apologize if I forgot something in my question, let me know.
For those who are curious, the code looks exactly like this (Can't be compiled as is):
g2d.setFont(new Font("Arial", Font.PLAIN, hierarchyWidth / 26));
g2d.setColor(Color.black);
int oYPos = 20;
// For every object in existence
for(int i=0; i < engine.sceneObjects.activeObjects.size(); i++) {
GameObject theObject = engine.sceneObjects.activeObjects.get(i);
// If the scrollbar is within range of the hierarchy
// (Based on HierarchyHeight so that it's resolution friendly)
if(oYPos >= hierarchyScroll && oYPos < hierarchyScroll + hierarchyHeight) {
// If the object has no parent
if(theObject.transform.parent == null) {
g2d.drawString(theObject.name, hierarchyPosition.x + 5, hierarchyPosition.y + oYPos);
} else { // If the object has a parent
}
}
oYPos += 20;
}
// Track the last oYPos so that the scrollbar can adjust itself accordingly
lastOYPos = oYPos;
My guess would be some sort of class create for each of these labels and a Boolean stored called isSelected, and then rendering the label according to the class, but this seems a bit more complicated than I'd like to do

Using drawLine Function in Other Function

I'm creating a game where I need to draw some lines and dots. I have a general function called paintDot (check code below) and I want to call it in a different function. I don't know how to call it, any help?
public void paintDot (Graphics g, int x, int y)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(x,y,15,15);
}
This is the other function/method where I need to call the drawing function:
ATM the coordinates are just hardcoded so I know it's working correctly.
As you can see, I'm calling the paintDot method with bad arguements. Don't know what argument should be placed at Graphics g
private void gameWindow (int dif)
{
this.removeAll();
areaImage = new JPanel ();
//distance between points = 75
//point grid = 7*6
areaImage.setBounds(50,50,675,600);
areaImage.setBackground(Color.WHITE);
areaImage.setBorder(BorderFactory.createLineBorder(Color.black));
add(areaImage);
answer = new JTextField();
answer.setBounds(835,200,150,50);
answer.setBorder(BorderFactory.createLineBorder(Color.black));
answer.setHorizontalAlignment(JTextField.CENTER);
answer.setFont(new Font("Verdana", Font.BOLD, 20));
add(answer);
info= new JLabel ("Write your answer here:");
info.setBounds(830,155,250,50);
info.setFont(new Font("Verdana", Font.BOLD, 12));
add(info);
checkAnswer = new JButton ("Check Answer");
checkAnswer.setBounds(835,310,150,50);
checkAnswer.addActionListener(this);
add(checkAnswer);
next = new JButton ("Next");
next.setBounds(835,410,150,50);
next.addActionListener(this);
add(next);
end = new JButton ("End Game");
end.setBounds(835,510,150,50);
end.addActionListener(this);
add(end);
revalidate();
repaint();
int x = 75,y=75;
for(int num=0;num<6;num++)
{
for(int xx=0; x<7;xx++)
{
paintDot (areaImage,x,y); // here is the problem
x=x*2;
}
y=y*2;
}
}
I have a general function called paintDot (check code below) and I want to call it in a different function
You can't.
Painting can only be done in the paintComponent() method.
You should NEVER be invoking paintComponent() directly.
All painting code MUST be in the paintComponent() method.
If you want to paint 7 dots. Then that painting code MUST be in the paintComponent() method which means the looping code would be in the paintComponent() method and then you invoke the paintDot(...) method from withing the loop. The painting of the dots must be done EVERY time Swing determines the component needs to be repainted.
You have asked several questions on this topic and the answer is always the same. Read the tutorial link you have been given and follow the examples. The tutorial draws a square, but the concept would be similar for drawing 7 dots.
So once again, read the tutorial, download the code and play with the working example. Start by changing the tutorial code to draw 7 dots. Once you understand how that works, then you add the logic to your real code.
The tutorial link is give to you for a reason. If there is something you don't understand in the tutorial, then ask a question, but don't post code that looks nothing like the example from the tutorial and wonder why it doesn't work!
You have this for:
for(int xx=0; x<7;xx++)
where you have an index called xx and you try to do a cycle. The problem is that you test for x < 7 instead of xx < 7 and since x is greater than 7, you will never get into the for.
You could extend JPanel and overwrite the drawing functions, such as the paintComponent(Graphics g) (Thanks camickr) or paintAll(Graphics g) (I believe) method.
You might also want to add a JLabel with a BufferedImage using createGraphics()
Please note if you are trying to make a full-fledged game, you would need a game loop and other stuff, which is NOT fun without a library.
This is not an attempt in shameless self-promotion, it's a suggestion.
IF you need a game loop, canvases, multiple screens and stuff,
a library could be the way to go.
I made the library j2D to make 2D games.

java game loop. a little help to beginner

#Override
public void run() {
while (running) {
currentState.update();
prepareGameImage();
// next line draws image(frame) to the screen
currentState.render(gameImage.getGraphics());
repaint();
}
// End game immediately when running becomes false.
System.exit(0);
}
private void prepareGameImage() {
if (gameImage == null) {
gameImage = createImage(gameWidth, gameHeight);
}
Graphics g = gameImage.getGraphics();
g.clearRect(0, 0, gameWidth, gameHeight);
}
this is a snippet of game loop. a little explanation from the book about how it works. In prepareGameImage() we prepare an off-screen image by creating and initializing the gameImage variable with a width of gameWidth and a height of gameHeight. (i dont get how this works --->) Next, on every frame, we clear this image using a rectangle of equal size to clear all images that have been drawn to the screen in the previous frame. This ensures that images from the previous frame do not bleed into the current frame. Every frame starts anew.
what i dont understand is last 2 lines of the snippet. value of gameImage.getGraphics(); gets stored inside of Graphics variableg. method g.clearRect(0, 0, gameWidth, gameHeight); should only affect variable g and should not affect value generated by gameImage.getGraphics(); could you explain how does the last 2 lines of code do the task - "images from the previous frame do not bleed into the current frame" :( :(
thanks
gameImage.getGraphics();
only passes the refference(does not make a copy) to the internal Graphics of the gameImage.
Lets say that gameImage is an instance of some class A that has a private variable of the type Graphics G.
And has a method for accessing that variable:
public Graphics getGraphics(){
return this.G;
}
as you can se... by calling the getGraphics, you only have a reference(pointer) to the graphics.
The "Graphics" element is something global to your program. It is managing all of your graphics, no matter where they are. But since it is this global thing, you can't just use a variable you define like, say, a String, but must get it from an existing object that has a reference to it. For example, every Image has a reference to the graphics object. The variable g you have is a reference to this element now and it can be used. This reference is then used in the next line to clear out the whole screen and previously created images so they do not bleed into the current frame.
(Note: This explaination may not be 100% accurate, but that's how it made me understand it in the first place.)

Translate/Rotate/Move a graphics object without messing up the whole screen

I'm coding a GUI that will be doing some graphics translations/rotations, etc.
My problem is that when I try to translate my graphics,
(a) The entire screen translates instead of my one little painted area
(b) The old paint stays there, leaving a big paint blob instead of a translated image
(c) If I use the clearRect method to allow me to avoid (b), the entire screen goes white and (a) is still a problem
my DrawPanel class (I called it "LaunchTubeImage" for whatever reason)
private class LaunchTubeImage extends JPanel {
private Color colour;
public LaunchTubeImage(Color color) {
super();
this.colour = color;
}
public void paintComponent(Graphics g) {
Graphics2D gg = (Graphics2D)g;
double theta = (double)angle.getValue();
theta = Math.toRadians(theta);
gg.rotate(theta,tubeImage.getSize().width/2 + 10,
tubeImage.getSize().height - 50);
g.setColor(colour);
g.clearRect(0,0,getWidth(),getHeight());
g.fillRect(tubeImage.getSize().width/2,
tubeImage.getSize().height - 100 , 10, 50);
}
}
where this is called in my code
tubeImage = new LaunchTubeImage(Color.MAGENTA);
angle.addChangeListener(new ChangeListener(){
public void stateChanged(ChangeEvent e) {
tubeImage.repaint();
}
});
Case 1: Comment out clearRect in that 1st block of code I posted
http://i58.tinypic.com/2d1l5w2_th.png
Black background as desired. Not rotated yet. Looks good so far.
http://oi60.tinypic.com/1zw1sm.jpg
Rotated it with my JSpinner... you see that the previous location was not removed (and note how my buttons randomly doubled and put themselves at the top of the screen).
Case 2: Keeping in the clearRect method
oi57.tinypic.com/2s84307.jpg
Layout is fine so far, but I wanted the background to be black
oi57.tinypic.com/4rde8x.jpg
Yay! It rotated. But note the weird behavior of that random "15" that appeared in my top right corner
oi58.tinypic.com/vymljm.jpg
And finally... when I resize the window you see that my entire screen was rotated - not just the pink image I wanted to rotate
Tips/fixes/advice? Thanks!! I hope I've provided enough information
(P.s. if you insist on us asking clear/useful questions.... then DON'T limit the number of images you can post... :/ )
The first line of an overridden paintComponent method should usually be super.paintComponent(g). On a JPanel, this will cause the drawing area to be cleared with the background color. If you want to clear the background with a different color, you can do this by manually filling a rectangle (clearRect is discouraged, see the JavaDoc), but of course, this has to be done before applying any transform.
So your method should probably look like this:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(colour);
g.fillRect(0,0,getWidth(),getHeight());
Graphics2D gg = (Graphics2D)g;
double theta = (double)angle.getValue();
theta = Math.toRadians(theta);
gg.rotate(theta,tubeImage.getSize().width/2 + 10,tubeImage.getSize().height - 50);
gg.fillRect(tubeImage.getSize().width/2,tubeImage.getSize().height - 100 , 10, 50);
}

How do I draw an interactive Graph/Lines in Java?

Solved.
I had a question before but it was very badly posted so here it goes again, according to better rules.
I want to create some style of a graph such as this image:
.
It's based on a physics law, Snell's Law. As of now I've managed to paint the graph it self with a basic Line2D.Double which you can see here (Line.java). Then all I need to do is, in the interface class, add the lines to the array in that class as so:
LinesArray.addLine(150 , 25 , 150 , 275);
And every time it adds a new one, it repaints as you can see in the code sample.
But the problem is that I have no idea how to make this interactive. I wanted to make it interactive, as in that you could actually move those lines and at the same time you move the first line, the second would move accordingly to the Snell's Law formula, which is:
n1 * sin( a1 ) = n2 * sin ( a2 )
Considering that a1 is the first (left) angle, and a2 the second (right) angle in the first image posted.
A perfect example of what I'd hope to achieve is this one.
And if interactive movement is too hard (I'm on a 2 days schedule), this example is also a possibility.
Correct me if I'm wrong but for the second one, all that I'd need to do is calculate the mouse's coordinates and draw and calculate everything from there.
Here (menu_ui.java) is my interface class, in which the method I'm currently working with the lines is "menuSnell()" and here (Snell.java is my Snell class which contains the logic. Apologies for portuguese comments but it's fairly simple code which you don't really need comments to understand, plus I've separated it into readable methods.
So basically, my question is how do I make those lines interactive in the way I've described above.
Thanks!
I am not a graphic expert, but I had similar work a long time ago. I had an object that I need to repaint. I created my own JPanel, which holds my objects that should be paint. Whenever something changed, I call repaint method on JPanel. It looked like this
http://sourceforge.net/p/scribbler-cvut/code/132/tree/Tuzka/src/cz/cvut/scribbler/panel/RewritableGlassPane.java.
private LinkedList<ColoredArea> background = new LinkedList<ColoredArea>();
/**
* Vykreslí všechny položky v senamu vykreslených obrazců
* #param g2d grafika k vykreslení
*/
public void paintShape(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (ColoredArea area : background) {
area.fill(g2d);
}
if (mouse != null && !block) {
g2d.setColor(mouse_color);
g2d.draw(mouse);
}
if (point!=null){
SetPointsDialog.paintPoints(point, maxPoint, parent.getChildsSize(), g2d);
}
}
#Override
public void paint(Graphics g) {
paintShape((Graphics2D) g);
}
#Override
protected void paintComponent(Graphics g) {
paintShape((Graphics2D) g);
}
Everything I need to paint was stored in background variable. When something I LinkedList changed, I invoke repaint () method on the window.
I have a full source code store here: http://sourceforge.net/projects/scribbler-cvut/ but it was my long term project, so it is a little bit big.

Categories