Okay, I am not sure how to describe this. I have made a Class called ScreenAreas that defines specific areas on the screen. Later on, I am drawing these ScreenAreas.
What I would like to do, is to couple Paint attributes (Color, strokeWidth, Shaddowsettings, etc) to these ScreenAreas, in such a way, that I don't have to reset all these attributes, when drawing them again.
This is my ScreenArea Class:
import android.graphics.Canvas;
import android.graphics.Paint;
public class ScreenArea {
private int xMin;
private int yMin;
private int xMax;
private int yMax;
private Paint paint;
public ScreenArea(int x1, int x2, int y1, int y2, Paint paint) {
this.setXMin(x1);
this.setXMax(x2);
this.setYMin(y1);
this.setYMax(y2);
this.paint = paint;
}
// I removed the getters and setters for clarity
public void draw(Canvas canvas){
canvas.drawRect(this.xMin, this.yMin, this.xMax, this.yMax, this.paint);
}
}
And in my main Class I am constructing them using:
paint.setColor(Color.rgb(10,10,10));
area1 = new ScreenArea (
0,
0,
100,
100,
paint);
paint.setColor(Color.rgb(100,100,100));
area2 = new ScreenArea(
20,
20,
80,
80,
paint);
When I try to draw them, I simply do:
area1.draw(canvas);
area2.draw(canvas);
Both of the area's will be given the same color, though. In fact they are given the last color used. Probably, this is because the Paint objects in the ScreenArea are simply pointing to the same Paint object in the main Class. The question is, how to solve this problem!
Anyone?
You should remember that Paint object has a copy constructor. So instead of:
this.paint = paint;
within your ScreenArea constructor, you can use:
this.paint = new Paint(paint);
The answer is good, but if for some reason you don't want to instantiate a new Paint (perhaps because you're inside onDraw(), which I realize is not the case here) then you can use Paint.set().
public void set (Paint src) Added in API level 1
Copy the fields from src into this paint. This is equivalent to
calling get() on all of the src fields, and calling the corresponding
set() methods on this.
Replace private Paint paint; with private Paint paint = new Paint(); and then this.paint = paint; (which just copies to pointer to the Paint object) with this.paint.set(paint); (which copies the fields from paint to this.paint.
Related
Hi guys I recently started developing an android game, but i have encountered an issue with drawRectangle.
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.BLACK);
canvas.drawRect(new Rect(100,100,100,100), new Paint(Color.WHITE));
}
this Doesnt seem to work, but i have already drew on screen using another class with a draw method using the same logic but im curious why this doesnt work
private Paint myPaint = new Paint();
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.BLACK);
myPaint.setColor(Color.WHITE);
canvas.drawRect(new Rect(100,100,100,100), myPaint);
}
this doesnt work either
There are three issues in your implementation:-
Paint object doesn't take color in constructor, it takes a flag.
So you could have done something like Paint p = new Paint(Paint.ANTI_ALIAS_FLAG) and then set the color as p.setColor(Color.WHITE).
The Rect object should be something like new Rect(0,0,100,100).
In your case [new Rect(100,100,100,100)] the rectangle will be drawn as a rectangle with 0 width,
0 height and its upper left coordinate will be (100,100) and its
bottom right coordinate will be (100,100).
NEVER create objects in onDraw.
Paint's constructor doesn't take a color. It takes integer flags. So you just made a really weird paint object with every flag set, but you didn't set the color.
See: https://developer.android.com/reference/android/graphics/Paint.html#Paint(int)
This worked
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.BLACK);
myPaint.setColor(Color.WHITE);
canvas.drawRect(testRect, myPaint);
}
Where
private Rect testRect = new Rect(0,0,100,100}
private Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Hello fellow programmers!
So to be honest here, i'm not sure if the title question is correct, and you will see why.
Before i explain what i do, and why, here is the code snippet:
JPanel playerPanel = new JPanel() {
public void paint(Graphics g) {
X = 1;
Y = 1;
g.drawImage(player.getScaledInstance(player.getHeight()/2, player.getWidth()/2, Image.SCALE_DEFAULT), X, Y, null);
}
};
So this a snippet from a custom class i made, and my question would be that, you see there is an X and Y variable, i can change their values , but that changes nothing on the impact of the actual program, my first question would be that can i change the X, and Y of this JPanel's image, and if so , how can i "refresh" the actual JPanel/Image so that it looks like it moved?
Some notes:
-the X, Y are global variables
-playerPanel is inside a procedure, and a global variable
-i can access X, Y since they are global variables from outside the class
I'm having a hard time actually writing down my problem... Hopefully you understand what i would like to accomplish.
You're main problem: Don't use an anonymous inner class if you want to give the class new mutable fields. Instead, create a separate class, it can be an inner class, but it can't be anonymous, give it fields that are needed with getters and setters. Also all that Luxx recommends is correct -- override paintCompoent, call the super method, don't declare the fields within a method...
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
public class PlayerDrawingPanel extends JPanel {
private int playerX;
private int playerY;
private Player player;
public PlayerDrawingPanel(int playerX, int playerY, Player player) {
this.playerX = playerX;
this.playerY = playerY;
this.player = player;
}
public void setPlayerX(int playerX) {
this.playerX = playerX;
repaint();
}
public void setPlayerY(int playerY) {
this.playerY = playerY;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(player.getImage(), playerX, playerY, this);
}
}
There is no need to create global variables.
You can use setBounds(x, y, w, h) from Swing's JComponent to move and resize the JPanel.
Though, you have to keep in mind that a Component cannot draw outside its borders. Meaning that the Graphics object that is passed into paint(Graphics g) comes clipped and translated to fit the Component from it's parent.
So, to solve your case, you can either make your JPanel take over the whole area in which you want to draw by using setBounds() or you can you the LayeredLayout from your root panel to draw anywhere.
Let me exemplify the last solution. Consider frame to be your JFrame and playerPanel the JPanel that you overwrote the paint() method:
frame.setGlassPane(playerPanel);
frame.getGlassPane().setVisible(true);
Now your playerPanel is at the topmost layer of your application, covering the whole area. This means you can draw anywhere over anything.
I have two paints and set their colors to different colors. The problem is that the second paint overrides the first paint.
That's my code:
public class Score {
static Globals g = Globals.getInstance();
private Rect bounds = new Rect();
private Paint paintBG = new Paint();
private Paint paintFG = new Paint();
private int mid;
public Score(Paint paint) {
this.paintBG = paint;
this.paintFG = paint;
// PROBLEME
paintBG.setColor(Color.GRAY);
paintFG.setColor(Color.WHITE); // <-- this paint overrides the paint before
}
public void draw(Canvas canvas) {
String score = String.valueOf(g.getScore());
paintFG.getTextBounds(score, 0, score.length(), bounds);
mid = (canvas.getWidth() / 2) - (bounds.width() / 2);
// different "paints" but the same color
canvas.drawText(score, mid, 60, paintBG);
canvas.drawText(score, mid, 50, paintFG);
}
}
Best regards from germany. :)
amahfouz has explained the problem. One solution to the problem is to use Paint's copy constructor.
public Score(Paint paint) {
paintBG = new Paint(paint);
paintFG = new Paint(paint);
paintBG.setColor(Color.GRAY);
paintFG.setColor(Color.WHITE);
}
This is expected. Both paints are referring to the same Paint object, the one passed as a parameter. So basically, both calls to setColor are modifying the same object and the last one is the one that sticks!
zum wohle!
Im trying to get the point of the cursor in the paint part and simply draw an oval. No luck though!
public void paint(Graphics g){
Point ComponentPoint = PaintPanel.getLocationOnScreen();
Point CursorPoint= MouseInfo.getPointerInfo().getLocation(); //gets cursor point
int ComPX = ComponentPoint.x;
int ComPY = ComponentPoint.y;
int CurPX = CursorPoint.x;
int CurPY = CursorPoint.y;
int FinalX = CurPX - ComPX;
int FinalY = CurPY - ComPY;
g.drawOval(FinalX, FinalY, 20, 20);
}
private void PaintPanelMouseDragged(java.awt.event.MouseEvent evt) {
//when mouse is moved over paintpanel
//PaintPanel.repaint();
not working
}
This is it without paint method, the image:
http://i.stack.imgur.com/VOyhr.png
You can't add code in the paint method like that. YOu would not reference the MouseInfo class in the paint method since you have no control over when the paint() method is invoked. You should be using a MouseListener and MouseMotionListner to do custom painting. Also, custom painting should not be done in the paint method.
See Custom Painting Approaches for two solutions.
I'm trying to develop a Java brick breaker (like DxBall) game and I want to make the Ball object with its own draw method.
What I'm trying to do:
public class Ball {
private int x, y, diameter;
public void Ball(){
x = 0;
y = 0;
diameter = 20;
}
public void draw(Graphics g){
g.setPaint(Color.red);
g.fillOval(x, y, diameter, diameter);
}
}
Therefore, my game engine extends JFrame and its paintComponent method will call game objects draw method. To sum, is it proper way to do object oriented game in Java? What should my Ball class extend?
Your Ball class seems to look ok. It doesn't need to extend anything. You will need to pass the Graphics object from the paintComponent of your game object to the Ball draw method.
If you wish to make Ball a graphical component, you could extend JComponent:
public class Ball extends JComponent {
private int x;
private int y
private int diameter;
public Ball() {
x = 0;
y = 0;
diameter=20;
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setPaint(Color.red);
g.fillOval(x, y, diameter, diameter);
}
}
and simply call repaint when you wish to paint the component instead of a custom draw method.
Note: There's no return type for constructors.
Your class is fine but I recommend extending a class. This class usually called as Sprite or Action or GameObject contains the basic information like
image (or animation), position, collision rect and some basic functions like get and set it's position, speed and some collision detection functions if you wish.
Some resources.
The Breakout game
GEJ - game-engine-for-java
Java-Gaming.org - Java Gaming Resources
Hope they help. And to draw the object, do
g.drawImage(ball.image, ball.x, ball.y, null);