GridBagLayout is not adding my panel - java

I am trying to add a three panels using GridBagLayout in JFrame. When the default layout is set, the panel is added without any problem, but when layout is changed to GridBagLayout and panel is added in JFrame, then the output is an empty frame.
Here is the code for MainFrame:
public class MainFrame extends JFrame {
CirclePanel[] cp;
MainFrame() throws IOException{
cp = new CirclePanel[3];
for(int i = 0 ;i <3 ; i ++)
cp[i]= new CirclePanel(i+1);
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());//when this line is not set then
//add(cp[0]) adds the panel
GridBagConstraints gc = new GridBagConstraints();
gc.weightx=1;
gc.weighty=1;
gc.gridx=0;
gc.gridy=0;
add(cp[1],gc);
this.setVisible(true);
}
}
I tried different step but was unable to add the panel using GridBagLayout or at least I was unable to show panel.
I want to add 3 consecutive panels with equal width by incrementing gc.gridx.
The Main class contains only the main method, which is calling the MainFrame constructor.
In my custom panel class (CirclePanel) I used the paintComponent method to draw circles.
public class CirclePanel extends JPanel {
private int mainCirclex ;//= getWidth()/2;
private int mainCircley ;//= getHeight()/2;
private final int mainCircler =1200;
private final double ampRadius = 0.1;
// private MakeArrays ma;
private int[] firstCir;
public CirclePanel(int num) throws IOException{
firstCir = new int[175];
/* ma = new MakeArrays();
if(num == 1)
firstCir = ma.getFirstCir();
else if(num == 2)
firstCir = ma.getSecondCir();
else if(num == 3)
firstCir = ma.getThirdCir();
*/
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
//////////main circle////////////////////
//amplifying radius and setting x & y
mainCircley = getHeight()/2;
mainCirclex = getWidth()/2;
int radius = (int) (mainCircler*ampRadius);
//drawing
g2d.setColor(Color.yellow);
g2d.drawOval(mainCirclex - radius, mainCircley - radius, 2 * radius, 2 * radius);
/////////end main circle///////////
//////////////sub circles//////////////
int min = Math.min(mainCirclex, mainCircley);
int r2 = Math.abs(min - radius) / 160;
int j =0;
for (int i = 0; i <360; i++) {
if(j>=175) break;
if(i%2==0){
double t = 2 * Math.PI * i / 360;
int r = (int) (firstCir[j]*ampRadius);
//System.out.println(firstCir[j]);
int x = (int) Math.round(mainCirclex + r * Math.cos(t));
int y = (int) Math.round(mainCircley - r * Math.sin(t));
g2d.setColor(Color.red);
g2d.fillOval(x - r2, y - r2, 2 * r2, 2 * r2);
j++;
}
}
}
}

I added all 3 panels by incrementing the gridx value. To make it work I did the following:
Added the line gc.fill = GridBagConstraints.BOTH to allow the panels to resize and fill extra space.
Called setBackground in the panels' constructor instead of fillRect in paintComponent. It saves you the trouble of calculating the size of the panel.
Overrode the getPreferredSize of the panels:
#Override
public Dimension getPreferredSize() {
int size = (int) (2 * mainCircler * ampRadius);
return new Dimension(size, size);
}
(You might want to redo the calculation.)
Called pack on the frame instead of setSize.
Explanation
The panels you are adding to the frame are empty from the layout manager's point of view - they don't have any child components. This means that panels will retain their default preferred is, which is 10x10 (System.out.println(cp[1].getPreferredSize())) and they will be added to the frame with those dimensions.
Custom painting is not taken into account automatically when computing the preferred size of a component. If the preferred size is too small for the painting, it will not be displayed (or only part of it will). Overriding the getPreferedSize method of the panels to give the correct dimensions will tell the frame how to display them when pack is called.
Edit: comment answer
When I call setBackground to color the panels in their constructor it works fine, but when I try to use fillRect in paintComponent then the 1st panel is colored, but the next 2 panels aren't. Why is that?
Because of a very common misunderstanding (which is why I recommended point 2).
The getXXX() (X, Y, Width, Height) do not state the following explicitly, but they are derived from getBounds(), which reads:
Gets the bounds of this component in the form of a Rectangle object. The bounds specify this component's width, height, and location relative to its parent.
(emphasis mine.) So the bounds are in the parent's coordinate system. However, Graphics.fillRect paints with the given bounds in the component's coordinate system (the Graphics object passed to paintComponent is for painting the component, not its parent).
Then in order to paint the panel in its own coordinate system, we need
g2d.fillRect(0, 0, getWidth(), getHeight());
because a component always starts at (0,0) in its own coordinate system. Using
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
takes the position of the panel in the parent and passes it to some non-special position in the panel. Moreover, if the panel is located in the parent's (300,300), but the panel is less than (300,300) in size, then the drawing in the panel would in theory start outside of the panel. So, you see no painting.
The first panel paints because its (0,0) coincides with its parent's (0,0).

Related

How can I remove the white background and how can i add a stick?

I am trying to create a Billiards game for my project and I am having difficulty in adding the stick and the balls at the same time. Also, when I add the balls the background of the JFrame goes white, it is actually supposed to be green (the color of the table).
Your help will be much appreciated.
I tried using Graphics. For example g2d.setBackground(Color.green). Which did not work
public class Practice_Window implements MouseListener, MouseMotionListener, KeyListener {
JFrame Practice_Mode = new JFrame();
Balls myBalls = new Balls();
Stick myStick = new Stick();
public void PracticeWindow()
{
Practice_Mode.setSize(1000, 500);
Practice_Mode.setVisible(true);
Practice_Mode.setResizable(false);
Practice_Mode.setTitle("Practice Mode");
Practice_Mode.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Practice_Mode.getContentPane().setBackground(new Color(0, 1, 0, 0.5f)); //Not visible after i add my balls
Practice_Mode.getRootPane().setBorder(BorderFactory.createMatteBorder(10, 10, 10, 10, Color.GREEN));
Practice_Mode.add(myBalls);
//Practice_Mode.add(myStick);
//JPanel p = new JPanel();
//Timer t= new Timer(10, myBalls);
}
//BALL CLASS
public class Balls extends JPanel implements ActionListener
{
double Size = 35;
double REDxSpeed = 5;
double REDySpeed = 5;
double REDSpeed = 0;
double YELLOWxSpeed = 2;
double YELLOWySpeed = 3;
double YELLOWSpeed = 0;
double WHITExSpeed = 4;
double WHITEySpeed = 2;
double WHITESpeed = 0;
double friction = 0.2;
boolean Collision = false;
Ellipse2D.Double red = new Ellipse2D.Double(200, 200, Size, Size);
Ellipse2D.Double yellow = new Ellipse2D.Double(300, 300, Size, Size);
Ellipse2D.Double white = new Ellipse2D.Double(150, 400, Size, Size);
Timer t = new Timer(10, this);
Balls()
{
t.start();
}
#Override
public void actionPerformed(ActionEvent e) //Things are moving here
{
//RED BALL
red.x += REDxSpeed;
red.y += REDySpeed;
REDSpeed = Math.sqrt(REDxSpeed*REDxSpeed + REDySpeed*REDySpeed);
repaint();
if(red.x < 0 || red.x > getWidth() - red.width)
{
REDxSpeed = -REDxSpeed;
}
if(red.y < 0 || red.y > getHeight() - red.height)
{
REDySpeed = -REDySpeed;
}
//YELLOW BALL
yellow.x += YELLOWxSpeed;
yellow.y += YELLOWySpeed;
YELLOWSpeed = Math.sqrt(YELLOWxSpeed*YELLOWxSpeed + YELLOWySpeed*YELLOWySpeed);
repaint();
if(yellow.x < 0 || yellow.x > getWidth() - yellow.width)
{
YELLOWxSpeed = -YELLOWxSpeed;
}
if(yellow.y < 0 || yellow.y > getHeight() - yellow.height)
{
YELLOWySpeed = -YELLOWySpeed;
}
//WHITE BALL
white.x += WHITExSpeed;
white.y += WHITEySpeed;
WHITESpeed = Math.sqrt(WHITExSpeed*WHITExSpeed + WHITESpeed*WHITEySpeed);
repaint();
if(white.x < 0 || white.x > getWidth() - white.width)
{
WHITExSpeed = -WHITExSpeed;
}
if(white.y < 0 || white.y > getHeight() - white.height)
{
WHITEySpeed = -WHITEySpeed;
}
Collision_Detection();
}
public void paintComponent(Graphics g) //DRAWING MY BALLS
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
//g2d.setBackground(Color.green);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.red);
g2d.fill(red);
g2d.setColor(Color.yellow);
g2d.fill(yellow);
g2d.setColor(Color.black);
g2d.fill(white);
}
//STICK CLASS
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.*;
public class Stick extends JPanel implements MouseListener, MouseMotionListener, ActionListener {
int xLocation = 50;
int yLocation = 50;
int Width = 50;
int Height = 15;
Rectangle2D.Double stick = new Rectangle2D.Double(200, 200, Width, Height);
Timer t = new Timer(10, this);
Stick()
{
t.start();
}
public void PaintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.ORANGE);
g2d.fill(stick);
}
I am having difficulty in adding the stick and the balls at the same time.
So why are you trying to write your entire application at once without doing any testing along the way? Why do you have Timers in the code? Why do you have KeyListeners?
Learn to develop applications one step at a time. Write a little code do some testing. When it works add more functionality. Get the basic right first before adding more complicated logic.
Practice_Mode.add(myBalls);
//Practice_Mode.add(myStick);
The default layout manager of a JFrame is the BorderLayout. By default, when you add a component to the frame (and don't specify a constraint) the component goes to the CENTER. Only a single component can be added to the CENTER so only the last component added will be visible.
Your basic design is wrong. You don't want to have separate panels for the balls and stick. You want to have a single "BilliardsGameBoard" panel that will paint multiple objects. So this panel will paint all the balls and the stick. This way all the objects are managed by the same class.
You should also not be creating individual objects with variable names. This limits the number of object you can control. Instead, keep the objects you want to paint in an ArrayList, then the painting method iterates through the ArrayList and paints each object.
See: get width and height of JPanel outside of the class for a working example of this approach.
I add the balls the background of the JFrame goes white,
Practice_Mode.getContentPane().setBackground(new Color(0, 1, 0, 0.5f));
Don't use alpha values when you specify your color. For green you can just use:
practiceMode.getContentPane().setBackground( Color.GREEN );
Your stick and balls are extending JPanel, which is typically used as a container to group a bunch of JComponents, which are buttons and UI elements. The graphical errors you see is likely Java trying to line up your panels side by side using the default BorderLayout, because it thinks you want panels of buttons and stuff when you are just trying to achieve freeform shapes.
A better approach would be to to render your stick and balls as primitive shapes on a JPanel, rather than as JPanels themselves. This is accomplished by making them implement Shape or at least giving them draw methods; the Primitives tutorial would be of use. This question also has somebody in a somewhat similar situation as yourself, and has answers relevant to you.

Scrolling through a JPanel within a JScrollingPanel

I'm trying to make a level editor for my platformer game, I want my levels to be 100 by 100 squares.
So far the editor works, but I can't scroll through the JPanel. I've been playing around and I've made a small test class to fiddle with which I'll post. If you run it, all it does it show the grid. However if I swap out two variables (I'll comment where) it can show an image and scroll according to the size of that image.
I want that scrolling ability only for the JPanel, so that I can scroll through my 100 x 100 square level.
import java.awt.BorderLayout;
public class ScrollPaneJ extends JFrame {
// setting the panels
private JPanel contentPane;
private JScrollPane scrollPane;
// dimensions/ variables of the grid
int size = 16;
int startX = 112;
int startY = 48;
int width = 30;
int height = 30;
// this is the grid
String[][] grid = new String[width][height];
// this is from the full editor class
String currentImage = new String("platform");
ImageIcon currentBackIcon = new ImageIcon("Resources/backdirttile.jpg");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
// adding the scrollpane
ScrollPaneJ frame = new ScrollPaneJ();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ScrollPaneJ() {
setTitle("Scrolling Pane Application");
setSize(new Dimension(300, 200));
setBackground(Color.gray);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// defining the top and bottom panels, bottom is what I think I'm
// drawing on, top is where the scrollpanel goes, I copied this code
// from the internet and I'm not too sure how it works
JPanel topPanel = new JPanel();
JPanel bottomPanel = new JPanel(new GridLayout());
bottomPanel.setLayout(new BorderLayout());
getContentPane().add(bottomPanel);
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel);
// this is the label I was talking about
Icon image = new ImageIcon("src/MenuDesign.jpg");
JLabel label = new JLabel(image);
// Create a tabbed pane
// if you set it to say label instead of bottomPanel, you can scroll
// through the size of the label
scrollPane = new JScrollPane(bottomPanel);
scrollPane.setBounds(40, 40, 100, 100);
// set it label here as well.
scrollPane.getViewport().add(bottomPanel);
// I was hoping this would force the scrollbar in but it does nothing
scrollPane
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBounds(50, 30, 300, 50);
JPanel contentPane = new JPanel(null);
contentPane.setPreferredSize(new Dimension(500, 400));
contentPane.add(scrollPane);
topPanel.add(scrollPane, BorderLayout.CENTER);
init();
}
public void init() {
// this sets the grid to empty
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
grid[x][y] = "";
}
}
}
#Override
public void paint(Graphics g) {
// this paints the grid
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
g2d.drawRect(x * size + startX, y * size + startY, size, size);
if (grid[x][y].equals("")) {
g2d.drawImage(currentBackIcon.getImage(),
x * size + startX, y * size + startY, null);
}
g2d.setColor(Color.black);
g2d.drawRect((x * size) + 1 + startX, (y * size) + 1 + startY,
size, size);
}
}
}
public void drawTile() {
// this isn't enabled which is why you can't paint the grid, however it
// would change the tile of the square you're mouse is on, to the
// current tile, it works and isn't really important for what i need
// help with
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int mouseX = (int) b.getX();
int mouseY = (int) b.getY();
int gMX = ((mouseX - 48) / 16) - 4;
int gMY = ((mouseY - 48) / 16) - 3;
grid[gMX][gMY] = currentImage;
repaint();
}
}
scrollPane.getViewport().add(bottomPanel); should be more like scrollPane.getViewportView(bottomPanel);
You shouldn't be painting directly to the frame, as child components can be painted without the notification to the parents, meaning that what ever you've painted could be partially wiped out. Instead, this kind of painting should be done within a custom component which acts as the JScrollPane's, JViewport's view.
A JScrollPane needs two things, first, the size that the component would like to be (the preferredSize) and the size of the viewport view. If the component doesn't implement the Scrollable interface, then the component's preferredSize is used to determine that as well. This is why a JLabel will work.
A JScrollPane has a JViewport as it's primary child component. The JViewport should only have a single component, typically assigned either via JScrollPane#setViewportView or JViewport#setView methods
See How to Use Scroll Panes for more details
Create a custom component that extends JPanel and override it's getPreferredSize method to return the size of the component you want. Override it's paintComponent method and perform you custom painting their.
Overlaying custom painting ontop of other components is more difficult
You can also add JScrollPane in your panel like this
JPanel p = new JPanel();
add(new JScrollPane(p));

How can I create a resizable bar with given instance variables and it two different colors set to it, red for (a) and green for (b)?

When I call the paintComponent to the frame I get a graphical display that is not resizable. How do I get the paintcomponent to paint a resizable object to the frame that will resize with the window using the given instance variables?
public class Program3Component extends JComponent
{
private static final long serialVersionUID = 5449209515657047425L;
private final int yTp = 20;
private final int xLt = 10;
private final int xRt = 10;
private final int yBtm = 40;
public void paintComponent(java.awt.Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
Rectangle bar = new Rectangle(10,10,300,70);
g2.draw(bar);
g2.setColor(Color.GREEN);
g2.setColor(Color.RED);
}
You use the size of the component you are painting, to determine the coordinates of your bar.
For example, if you want a bar that is 10 pixels away from each side of the component:
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle bar = new Rectangle(10,10,getWidth() - 20, getHeight() - 20 );
g2.setColor(Color.GREEN);
g2.draw(bar);
}
The reason to deduct 20 from the width (or height) is that the width of the bar is the width of the window, but with a margin of 10 on both sides.
You can use the components getWidth and getHeight properties to determine the current size of the component.
You can also override the getPreferrdSize method to define the "preferred size" you would the component to be normally
For example, based on the values you have, the preferred size would be xLt + xRt x yTp + yBtm

JPanel only showing one object

I've made 20 objects from my Ball class, as I need 20 balls bouncing around on the screen, but right now it only shows 1 ball bouncing around.
I think it has something to do with 20 JPanels being added and they are overlapping each other, but I'm not entirely sure.
package com.company;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
* Created by John on 25/02/2015.
*/
public class Ball extends JComponent{
int _speedX;
int _speedY;
int _size;
int _x;
int _y;
Color _color;
int _windowX;
int _windowY;
Ball(int x, int y, int sz, int sX, int sY, Color c, int windowX, int windowY){
_x = x;
_y = y;
_speedX = sX;
_speedY = sY;
_size = sz;
_color = c;
_windowX = windowX;
_windowY = windowY;
setForeground(_color);
}
public void update(){
_x = _x + _speedX;
_y = _y + _speedY;
if (_x<0 || _x>_windowX-_size){
_speedX*=-1;
}
if (_y<=0 || _y>_windowY-_size){
_speedY*=-1;
}
this.repaint();
}
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.fillOval(_x, _y, _size, _size);
}
public static void main(String[] args) {
// write your code here
JFrame frame = new JFrame("Title"); //create a new window and set title on window
frame.setSize(600, 600); //set size of window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set the window to close when the cross in the corner is pressed
frame.setVisible(true); //make the window visible
JPanel panel = new JPanel();
frame.add(panel);
Ball[] balls = new Ball[20];
for(int i = 0; i<20;i++){
balls[i] = new Ball(randInt(0,600),randInt(0,600),randInt(10,20),randInt(1,8), randInt(1,8),Color.yellow,600,600);
panel.add(balls[i]);
}
while(true){
for(int i = 0; i < balls.length; i++) {
balls[i].update();
}
panel.repaint();
try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
Suggestions:
Don't make Ball extend JComponent or JPanel, but instead make it a logical non-component class.
Create a Drawing class that extends JPanel and draw in its paintComponent method, not its paint(...) method. This will lead to smoother animation.
Create an ArrayList<Ball> of your Ball objects and draw them inside of the paintComponent(...) method override by iterating through the list.
Same for moving the Balls held by the List.
Use a Swing Timer to drive your animation, not a while (true) loop. If you make one mistake with that loop, you'll freeze your GUI rendering it non-functioning, and so the Swing Timer is a much safer way to do this.
it only shows 1 ball bouncing around.
I'm surprised you even see one. You shouldn't see any.
I think it has something to do with 20 JPanels being added and they are overlapping each other,
The problem is that by default a JPanel uses a FlowLayout. When you add a component to the panel the panel will respect the preferred size of the component. You are using a custom component and the default size is (0, 0) since you didn't provide one.
If you want to continue this approach by using a custom component then you need to:
use the properties of the component to control the size and location of the component on the panel. That is you can use the setSize(...) method and setLocation(...) method. You don't need your _x, _y and _size variables. You also don't need the color variable because you can use setForeground(...) to set the color of your component.
Override the getPreferredSize() method to return the size of the ball.
Override the 'paintComponent(...)` method to fill the oval with an x/y value of 0, since the painting needs to be done relative to the ball, not the panel.
In the update() method you use the setLocation(...) method to set the location of the component on the panel.
Now you also need to use a null layout on your panel so the balls can move randomly.
I don't recommend this approach for your final solution, but it is a good exercise to implement this logic to understand how you might go about creating a custom component and how painting is done on this component. Understanding this concept will help you better understand how Swing works in general.

Drawing strings inscribed in a circle

I am aware of Java's drawString(String str, int x, int y) method; however, sometimes all I want is to label a circle with an appropriate string in the middle of it, given a font size (either in pts or in accordance to the circle's size). Is there an easy way to do it, or does one have to make the math on one's own? And if so, how can the width of a string be calculated, as a function of the font size (int pts)?
Here's an example. The text drawing is a modified version of the answer listed by Software Monkey, to use given coordinates, instead of drawing in the center of a component.
If you wanted to draw a circle that didn't cover the entire component, you would then have to calculate the center of the circle, and pass it into drawCenteredText.
The business with the Random class is there to demonstrate how this method will work with any font size.
public class LabledCircle {
public static void main(String args[]) {
JFrame frame = new JFrame();
// Create and add our demo JPanel
// I'm using an anonymous inner class here for simplicity, the paintComponent() method could be implemented anywhere
frame.add(new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw a circle filling the entire JPanel
g.drawOval(0, 0, getWidth(), getHeight());
Random rad = new Random();// For generating a random font size
// Draw some text in the middle of the circle
// The location passed here is the center of where you want the text drawn
drawCenteredText(g, getWidth() / 2, getHeight() / 2, rad.nextFloat() * 30f, "Hello World!");
}
});
frame.setSize(200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void drawCenteredText(Graphics g, int x, int y, float size, String text) {
// Create a new font with the desired size
Font newFont = g.getFont().deriveFont(size);
g.setFont(newFont);
// Find the size of string s in font f in the current Graphics context g.
FontMetrics fm = g.getFontMetrics();
java.awt.geom.Rectangle2D rect = fm.getStringBounds(text, g);
int textHeight = (int) (rect.getHeight());
int textWidth = (int) (rect.getWidth());
// Find the top left and right corner
int cornerX = x - (textWidth / 2);
int cornerY = y - (textHeight / 2) + fm.getAscent();
g.drawString(text, cornerX, cornerY); // Draw the string.
}
}

Categories