I have coordinates of rectangle to draw and I want to centre some text inside this rectangle.
int x, y, width, height;
String str = "This is a text";
x = 15;
y = 15;
width = 20;
heights = 30;
g.drawRect(x, y, width, height);
g.drawString(str, x + width/2, y + height/2);
If you want to center the text then you need to know the length of the text so you know its width relative to the width of the rectangle. This is done by getting the FontMetrics instance from the Graphics object.
So the basic code would be:
FontMetrics fm = g.getFontMetrics();
int stringWidth = fm.getStringWidth(...);
int xDiff = (width - stringWidth) / 2;
g.drawString(str, x + xDiff, ...);
Of course you will also need to center based on the height.
Doc says...
public abstract void drawString(String theString,
int x,
int y)
Renders the text of the specified iterator applying its attributes in accordance with the specification of the TextAttribute class.
The baseline of the leftmost character is at position (x, y) in this graphics context's coordinate system.
So... you are drawing your string starting at the center point of the rect but not the string.
https://docs.oracle.com/javase/7/docs/api/java/awt/FontMetrics.html - get the font metrics from the gc and figure out how wide the string is. Then subtract half of that from the start x. Do something similar for y (remember that height doesn't start at base.)
Related
I need some assistance fixing my vertical health bar. It tracks health correctly and updates, but because of how Java draws (from the top left corner, i.e. (0,0)), the bar appears to be upside down. I would like to flip the health bar so it would appear correctly but I am unsure how to do so.
The division in the codes x and y is just to place the bar in the correct position on the canvas. The multiplier is to scale up the health bar to fit a graphical overlay I made for it.
private void drawHealthBar(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(WIDTH - (WIDTH / 50), HEIGHT / 2, 10, ships.get(0).getHealth() * 6);
}
Setup the coordinate system how you want, using transform() and translate(). So:
you want the origin to be at (0, height); bottom left.
then you want to flip the Y axis.
Example code:
AffineTransform tform = AffineTransform.getTranslateInstance( 0, height);
tform.scale( 1, -1);
g2.setTransform( tform);
you need to shift bar depending on amount of health left, like this:
private void drawHealthBar(Graphics g) {
final Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
final int w = 10;
final int h = ships.get(0).getHealth() * 6; // calculate height first
final int x = WIDTH - (WIDTH / 50);
final int y = HEIGHT / 2 + (MAX_HEIGHT - h); // shift by height of whitespace
g2.fillRect(x, y, w, h);
}
I'm making a 2D card game. In it I have a custom font uses drawString from the Graphics library to draw it in with custom color and size. Problem is that this seems incredibly unoptimized. I can't seem to find out why. With 5 cards on screen, each one using this method 4 times each, I got from 3,800 fps down to 350 fps. Here's the way I draw text:
public static void drawString(Graphics g, String text, int xPos, int yPos, boolean center, Color c, Font font) {
g.setColor(c);
g.setFont(font);
int x = xPos;
int y = yPos;
if (center) {
FontMetrics fm = g.getFontMetrics(font);
x = xPos - fm.stringWidth(text) / 2;
y = (yPos - fm.getHeight() / 2) + fm.getAscent();
}
g.drawString(text, x, y);
}
After a bit of googling here's how I did it. This image is created when a Card UI element is added to the screen. Then is used to just overlay on the card's image. The x and y scaling is done in a separate class. The code mentioned in the original comment is in the Text class, along with the other drawRestrictedText method:
public BufferedImage createTextOverlayImage(){
BufferedImage overlay = new BufferedImage(imageWidth, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = overlay.createGraphics();
Text.drawString(g, name,
(imageWidth / 2) + wd.getScaleX(18),
wd.getScaleY(21),
true,
Color.black, Assets.font20Bold);
Text.drawString(g, cost + "",
wd.getScaleX(28),
wd.getScaleY(28),
true,
Color.blue, Assets.font28Bold);
Text.drawRestrictedString(g, keyWords,
wd.getScaleX(20),
wd.getScaleY(162),
imageWidth,
Color.magenta,
Assets.font18Bold);
Text.drawRestrictedString(g, description,
wd.getScaleX(20),
wd.getScaleY(185),
imageWidth - wd.getScaleX(35),
Color.black,
Assets.font18);
return overlay;
}
Here's the site I used for reference: http://www.java2s.com/Tutorials/Java/Graphics_How_to/Text/Write_text_onto_image.htm
Question about the circumference of circles. In order to change the outside color of the circle (circumference) I would use
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
Just not exactly how to start off after the following code below..after Public void drawArc I dont know where to go
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension d = getSize();
for(int i = 0; i < 100; ++i) {
Color color = new Color(generator.nextInt(255), generator.nextInt(255), generator.nextInt(255));
g.setColor(color);
int circleSize = generator.nextInt(d.width / 4);
int x = generator.nextInt(d.width - circleSize);
int y = generator.nextInt(d.height - circleSize);
g.fillOval(x, y, circleSize, circleSize);
g.drawArc(x, y, circleSize, circleSize, 0, 360);
}
}
You are drawing the body of a circle, then drawing its outline, without changing the colour in between. That means you can't actually see the outline of the circle.
I think you should change the colour of the graphics context, before you draw the outline. One way would be to insert
color = new Color(generator.nextInt(255), generator.nextInt(255), generator.nextInt(255));
g.setColor(color);
before the call to drawArc.
You don't need your own drawArc method, you should be calling the Graphics.drawArc() method. x and y are the center of the circle, width and height are the diameter of the circle, and startAngle and arcAngle are where to start and stop drawing the circle. 0 is 3 o'clock. So to draw a complete circle you would use 0 and 360 for startAngle and arcAngle.
Hello i'm currently working on a 2D Game Engine written entirely in java. Is there a way to centre a Graphics Object (g.drawString(x,y,z).
It would be preferably if this could be done through Graphics and the DefaultToolkit.
Thankyou very much :)
Simple mathematics. We have the object to be centered and the area where it should be centered.
Object width - w
Object height - h
Area width - aW
Area height - aH
//Follow center coordinates are coordinates where top left corner should be placed in order for the object to lie in center
centerWidth = (aW - W) /2
centerHeight = (aH - H) /2
As you can see, you MUST know the metrics of area you are placing your object on !
If that area is just the screen, then screen dimension can be used like this.
//Some dummy object metrics
int w = 30;
int h = 60;
//Now we find out the area metrics
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int aW = screenSize.width;
int aH = screenSize.height;
//Apply our common formula
int centerWidth = (aW - w) / 2;
int centerHeight = (aH - h) /2;
This works well for objects you know (their width and height).
Text centering
If you want to center text, you can use FontMetrics class, which allows you to measure size of text.
I have another question, this is also extra credit and not homework. This time I need to create a border with out using java2d. The instructions are...
Write a method called drawRectangleBorder having six parameters which does not use the graphics package. It draws a rectangular border starting at the x and y coordinates given as the first two parameters, having a width and height given by the third and fourth parameters, the width of the border given by the fifth parameter in the color given by the sixth parameter. The parameter list is: x, y, width, height, borderWidth, color
I used a previous method I made to create a border around the outside of a picture but the best I can make it do now is a couple scattered boxes. The most recent version will not show anything
public void drawRectangleBorder(
int x, int y, int width, int height, int border, Color newColor) {
int startX = 0;
int startY = 0;
// top and bottom
for (startX = x; x < width; x++) {
for (startY = y; y < border; y++) {
// top pixel
this.getPixel(startX, startY).setColor(newColor);
// bottom pixel
this.getPixel(startX + width, startY + height).setColor(newColor);
} // for-y
} // for-x
// left and right
for (startX = x; x < border; x++) {
for (startY = y; y < height; y++) {
// left pixel
this.getPixel(startX, startY).setColor(newColor);
// right pixel
this.getPixel(startX + width, StartY + height).setColor(newColor);
} // for-y
} // for-x
return;
} // end drawRectangleBorder
Again I thank you for any input.
You can alter the pixels in a java.awt.BufferedImage as shown here.
I might be too sleepy but I think your forgetting to set the pixel back into this (whatever this is ^^)
I'm guessing this.getPixel sends your back a copy so you might want to do something like
Pixel p = this.getPixel( startX, startY );
p.setColor(newColor);
this.setPixel(startX, startY, p);