Spikatrix
Spikatrix

Reputation: 20244

How do I draw a letter inside a painted circle with random size and random coordinates?

I have a class which extends JPanel. The size of the JPanel is set by adding the following method in the class:

@Override
public Dimension getPreferredSize() {
    return new Dimension(WIDTH, HEIGHT);
}

the relevant fields of this class are:

int position = 0;

int randomSize = 0; 
int randomPositionX = 0;
int randomPositionY = 0;

public final static int MAX_SIZE = 100;
public final static int MIN_SIZE = 10;

public final static int WIDTH    = 500;
public final static int HEIGHT   = 500;

private Random rand = new Random();

String alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

I choose a random size (Maximum of 100 and minimum of 10) and a random coordinate from a method. I also choose a random index for the string alphabets:

randomSize = MIN_SIZE + (rand.nextInt(MAX_SIZE - MIN_SIZE) + 1);

randomPositionX = rand.nextInt(WIDTH - randomSize);
randomPositionY = rand.nextInt(HEIGHT - randomSize);

position = rand.nextInt(alphabets.length());

My attempt at drawing the letter and circle:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g); 
    g.fillOval(randomPositionX, randomPositionY, randomSize, randomSize);
    g.setFont(new Font("TimesRoman", Font.PLAIN, randomSize));
    g.setColor(Color.RED);
    g.drawString(alphabets.charAt(position) + "", randomPositionX + (randomSize/2), randomPositionY + (randomSize/2));
}

But it doesn't draw the letter at the center of the circle. In short, the problematic line is

g.drawString(alphabets.charAt(position) + "", randomPositionX + (randomSize/2), randomPositionY + (randomSize/2));

How do I achieve what I want?


MCVE as requested:

import javax.swing.JFrame;
import javax.swing.JPanel;

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

import java.util.Random;

class MCVE{

    static int randomSize = 0; 
    static int randomPositionX = 0;
    static int randomPositionY = 0;

    static int position = 0;

    public final static int MAX_SIZE = 100;
    public final static int MIN_SIZE = 10;

    public final static int WIDTH    = 500;
    public final static int HEIGHT   = 500;

    private static Random rand = new Random();

    static String alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static void main(String[] argv){

        randomSize = MIN_SIZE + (rand.nextInt(MAX_SIZE - MIN_SIZE) + 1);

        randomPositionX = rand.nextInt(WIDTH - randomSize);
        randomPositionY = rand.nextInt(HEIGHT - randomSize);

        position = rand.nextInt(alphabets.length());

        JFrame frame = new JFrame("Test");
        JPanel panel = new JPanel(){
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g); 
                g.fillOval(randomPositionX, randomPositionY, randomSize, randomSize);
                g.setFont(new Font("TimesRoman", Font.PLAIN, randomSize));
                g.setColor(Color.RED);
                g.drawString(alphabets.charAt(position) + "", randomPositionX + (randomSize/2) - 15, randomPositionY + (randomSize/2) + 15);
            }
        };

        frame.add(panel);
        frame.setSize(WIDTH, HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Problem: The letter doesn't get drawn in the center of the circle.

Upvotes: 1

Views: 803

Answers (1)

Strikeskids
Strikeskids

Reputation: 4052

Graphics drawString draws the characters with the lower left corner of the text at the point specified. You will need to do some math in order to center them like you want.

First, we need to get the FontMetrics from the Graphics object we are using. Presumably, you will have already changed the font to the one you want.

FontMetrics metrics = g.getFontMetrics(g.getFont());

Now, we need to find the size of the text we will be drawing:

Rectangle2D bounds = metrics.getStringBounds(text, g);

Next, use these bounds to offset the text being drawn:

int offsetX = -bounds.getWidth()/2;
int offsetY = -bounds.getHeight()/2;
g.translate(offsetX, offsetY);
g.drawString(text, x, y);
g.translate(-offsetX, -offsetY);

Alternatively, bundle the offsets directly into the drawing call

int offsetX = -bounds.getWidth()/2;
int offsetY = -bounds.getHeight()/2;
g.drawString(text, x+offsetX, y+offsetY);

Upvotes: 1

Related Questions