I have two classes. The first class is called Fishy1, and the second class is called Fishy2. This is the code for my first class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Fishy1 extends JPanel {
Fishy1 fishy1 = new Fishy1();
/* Graphics goes here */
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(50, 50, 50, 50);
}
}
As you can see, the code basically draws an oval in fishy1. And here is the code for my second class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Fishy2 extends JPanel {
Fishy2 fishy2 = new Fishy2();
}
As you can see, in the second class, there is no paintComponet method to draw to fishy2. So, my question is, is there a way to draw to the second class using the paintComponent method in the first class? If there's no way to do it, please let me know. Thank you.
To achieve graphics replication between 2 swing classes at same time
public class Fishs extends JPanel {
//Static list, all fishes panel will display the same objects at same positions
private static List<OvalObj> lstOvalObjects;
public Fishs() {
//if the list is null just initialize it.
lstOvalObjects = lstOvalObjects == null? new ArrayList():lstOvalObjects;
}
/* Graphics goes here */
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
lstOvalObjects.forEach(ovalObject -> g.drawOval(ovalObject.getX(), ovalObject.getY(), ovalObject.getWidth(), ovalObject.getHeight()));
}
public static List<OvalObj> getLstOvalObjects() {
return lstOvalObjects;
}
public static void setLstOvalObjects(List<OvalObj> lstOvalObjects) {
Fishs.lstOvalObjects = lstOvalObjects;
}
}
The oval object:
public class OvalObj{
private int x,y,width,height;
public OvalObj(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Implementation:
//First Frame
JFrame frame1 = new JFrame();
frame1.setLayout(new BorderLayout());
//First Fish Panel that will go to frame1
Fishs fish1 = new Fishs();
fish1.setVisible(true);
frame1.add(fish1, BorderLayout.CENTER);
frame1.pack();
frame1.setVisible(true);
//Second Frame
JFrame frame2 = new JFrame();
//Second Fish Panel that will go to frame2
Fishs fish2 = new Fishs();
fish2.setVisible(true);
frame2.setLayout(new BorderLayout());
frame2.add(fish2, BorderLayout.CENTER);
frame2.pack();
frame2.setVisible(true);
/// you can add many objects to draw as you like in a static way anywhere in your code, they will render in every fish panel at same time
Fishs.getLstOvalObjects().add(new OvalObj(0, 0, 50, 50));
Fishs.getLstOvalObjects().add(new OvalObj(20, 20, 50, 50));
Related
My purpose - to create a board with lines, using Java Swing.
After I made a board and added color to it, I tried to produce lines. To do this, I inherit from JPanel and added paintComponent method. But when I run the application, the method is not called.
I added default constructor with super();
I also added to the called constructor super();
I still cannot make the paint method or the paintComponent method to get run;
I tried all of the following posts:
Java Swing paint() not working
Insert Button in JPanel
public class Main {
public static void main(String[] args) {
Board board = new Board(295, 295, "Go board");
}
}
import java.awt.*;
import javax.swing.*;
public class Board extends JPanel{
private int width;
private int height;
private String title;
private JFrame JFrame;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public JFrame getJFrame() {
return JFrame;
}
public void setJFrame(JFrame JFrame) {
this.JFrame = JFrame;
}
public Board(int width, int height, String title){
super();
this.width = width;
this.height = height;
this.title = title;
this.initBoard();
}
public Board(){
super();
}
public void initBoard(){
JFrame f = new JFrame(this.getTitle());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setBackground(Color.getHSBColor(25, 75, 47));
f.setSize(this.getWidth(), this.getHeight());
f.setLocation(550, 25);
f.setVisible(true);
this.setJFrame(f);
}
public void paint(Graphics g) {
g.drawLine(10, 10, 250, 10);
System.out.println("Test paint");
}
public void paintComponent(Graphics g) {
g.drawLine(10, 10, 250, 10);
System.out.println("Test paintComponent");
}
}
You never have called your initBoard which contains JFrame (which is bad design). Also you must add your panel to that frame with jframe.add(this);
It would be better to have your frame alone, and add your component to it like this
public static void main(){
JFrame f=new JFrame();
///set all the dimensions and other stuff of the frame
f.setLayout(new BorderLayout);
f.add(new Board(295, 295, "Go board"),BorderLayour.CENTER);
f.setVisible();
}
im trying to draw 20 rectangles on screen at once using two different classes, one for the frame and one for each rectangle, However only 1 is being drawn. here is the window class
private final List<Vehicle> vehicles = new ArrayList<>();
public Window() {
this.initWindow();
this.populateVehicles();
}
private void initWindow() {
this.setSize(1440, 920);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Steering");
this.setVisible(true);
}
public void populateVehicles() {
for (int i = 0; i < 20; i++) {
int x = Util.getRandomInt(10, 1000);
int y = Util.getRandomInt(20, 800);
Vehicle v = new Vehicle(x, y);
this.add(v);
vehicles.add(v);
System.out.print("printing new rect # " + x + " : " + y + "\n");
}
}
private void repopulateVehicles() {
if (this.vehicles.isEmpty()) return;
for (Vehicle v : vehicles) {
v.repaint();
}
}
public void refresh(boolean hard) {
this.repopulateVehicles();
if (hard) {
SwingUtilities.updateComponentTreeUI(this);
}
}
}
and here is the rectangle class
public class Vehicle extends JPanel {
private int x;
private int y;
private int speed;
private final int width;
private final int height;
public Vehicle(int x, int y) {
this.x = x;
this.y = y;
this.width = 25;
this.height = 10;
}
public void moveVehicle(int x_, int y_) {
this.x += x_;
this.y += y_;
this.repaint(x, y, x_, y_);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Color c = new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
g2d.setColor(c);
g2d.rotate(Math.toRadians(30));
g2d.fillRect(this.x, this.y, this.width, this.height);
}
public Dimension getPreferredSize() {
return new Dimension(this.width, this.height);
}
}
the output is just 1 rectangle being drawn on the frame, while is should be that 20 rectangles are being drawn. the debug print statement shows that each is being drawn at different coords but they arent being shown.
The default layout manager for the content pane of a JFrame is the BorderLayout.
By default each component is added to the CENTER of the BorderLayout. Only the last component added will be given a size/location. So only the last component will be visible.
The solution is:
to display components at random locations you will need to use a null layout on the content pane.
you will need to set the size of each component equal to the preferred size, otherwise the default size will still be (0, 0) and there is nothing to paint.
you will need to set the size of each location, otherwise the default will be (0, 0)
the "random" color of the Vehicle should be assigned in the constructor, not the painting method. A painting method should only paint the current state, not change the state of the component.
Note:
This answer only addresses the issues of using a JPanel to represent your Vehicle. You need to understand how a layout manager works to give components a size/location. In this case because you are randomly positioning components on the panel you would need to use a null layout and set the size/location yourself.
This is not the preferred approach. The better approach is to do custom painting yourself of all the Vehicles as demonstrated by Gilbert.
I rearranged your code to create this GUI. I shrank it down to fit better in the answer.
It's a really good idea to separate your code into a model / view / controller (MVC) pattern. This allows you to separate your concerns and focus on one part of the application at a time.
I made your Vehicle class a plain Java getter / setter class that holds one vehicle.
I created a Roadway class to hold the List of Vehicle instances. The Roadway class is another plain Java getter / setter class.
I renamed your Window class DrawingPanel and made it a drawing JPanel. The DrawingPanel class just draws the List of Vehicle instances from the Roadway class. Period.
I created a VehicleListener class to move the vehicles.
I put the JFrame code into a separate class that calls all the other classes.
I made all the classes inner classes so I could post the code as one block.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class VehicleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new VehicleGUI());
}
private final Dimension drawingPanelDimension;
private DrawingPanel drawingPanel;
private final Roadway roadway;
public VehicleGUI() {
this.drawingPanelDimension = new Dimension(400, 200);
this.roadway = new Roadway(drawingPanelDimension);
}
#Override
public void run() {
JFrame frame = new JFrame("Steering");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.drawingPanel = new DrawingPanel(roadway,
drawingPanelDimension);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
Timer timer = new Timer (100, new VehicleListener(this, roadway));
timer.setInitialDelay(3000);
timer.start();
}
public void repaint() {
drawingPanel.repaint();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Roadway roadway;
public DrawingPanel(Roadway roadway,
Dimension drawingPanelDimension) {
this.roadway = roadway;
this.setBackground(Color.WHITE);
this.setPreferredSize(drawingPanelDimension);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Vehicle vehicle : roadway.getVehicles()) {
g2d.setColor(vehicle.getColor());
g2d.fillRect(vehicle.getX(), vehicle.getY(),
vehicle.getWidth(), vehicle.getHeight());
}
}
}
public class VehicleListener implements ActionListener {
private final Roadway roadway;
private final VehicleGUI frame;
public VehicleListener(VehicleGUI frame, Roadway roadway) {
this.frame = frame;
this.roadway = roadway;
}
#Override
public void actionPerformed(ActionEvent event) {
for (Vehicle vehicle : roadway.getVehicles()) {
vehicle.moveVehicle();
}
frame.repaint();
}
}
public class Roadway {
private final Dimension drawingPanelDimension;
private final List<Vehicle> vehicles;
private final Random random;
public Roadway(Dimension drawingPanelDimension) {
this.drawingPanelDimension = drawingPanelDimension;
this.vehicles = new ArrayList<>();
this.random = new Random();
populateVehicles();
}
private void populateVehicles() {
int width = drawingPanelDimension.width;
int height = drawingPanelDimension.height;
for (int i = 0; i < 20; i++) {
int x = random.nextInt(width - 40) + 20;
int y = random.nextInt(height - 40) + 20;
Vehicle v = new Vehicle(x, y, drawingPanelDimension);
vehicles.add(v);
}
}
public List<Vehicle> getVehicles() {
return vehicles;
}
}
public class Vehicle {
private double x;
private double y;
private final int width;
private final int height;
private double speed;
private final Color color;
private final Dimension drawingPanelDimension;
public Vehicle(int x, int y, Dimension drawingPanelDimension) {
this.x = x;
this.y = y;
this.width = 25;
this.height = 10;
this.drawingPanelDimension = drawingPanelDimension;
this.speed = Math.random() * 20.0 - 10.0;
int red = (int) (Math.random() * 128.0);
int green = (int) (Math.random() * 128.0);
int blue = (int) (Math.random() * 128.0);
this.color = new Color(red, green, blue);
}
public void moveVehicle() {
this.x += speed;
this.x = (this.x < 0) ? drawingPanelDimension.width + this.x : this.x;
this.x = (this.x > drawingPanelDimension.width) ?
this.x - drawingPanelDimension.width : this.x;
}
public int getX() {
return (int) Math.round(x);
}
public int getY() {
return (int) Math.round(y);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Color getColor() {
return color;
}
}
}
I'm writing minesweeper and I want to put ovals on mine cells after a mine is clicked. But for now, I just want to put ovals on all cells just to check. I have written the code below. But when I run the program there is no ovals on buttons. I can not see the reason. I would be grateful if I get some suggestions.
public class Cell extends JButton{
...
public void painComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.orange);
g.drawOval(0,0,25,25);
}
public void draw() {
repaint();
}
...
}
public class Grid extends JPanel implements MouseListener{
...
public Grid(){
this.setLayout(new GridLayout(20,20));
cells = new Cell[20][20];
for(int i=0; i<20; i++) {
for(int j=0; j<20; j++) {
cells[i][j] = new Cell(i,j);
cells[i][j].addMouseListener(this);
cells[i][j].draw();
this.add(cells[i][j]);
}
}
plantMines();
setVisible(true);
}
...
}
but when I run the program there is no ovals on buttons.
public void painComponent(Graphics g) {
You made a typo. You spelt "paint" wrong.
When you override a method you should use:
#Override
protected void paintComponent(Graphics g)
This way if you make a typo the compiler will tell you that you are not overriding a method of the class.
Also, don't attempt to draw the oval by using custom painting. Instead you should be adding an Icon to the button. Then you can just change the Icon as required.
You can easily create an simple Icon to use. Here is an example of creating a square Icon:
import java.awt.*;
import javax.swing.*;
public class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JPanel panel = new JPanel( new GridLayout(2, 2) );
for (int i = 0; i < 4; i++)
{
Icon icon = new ColorIcon(Color.RED, 50, 50);
JLabel label = new JLabel( icon );
label.setText("" + i);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
panel.add(label);
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setSize(200, 200);
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}
I have to produce a randomly-sized shape (from 50 to 300 pixels) in a java GUI. There is a JList of 3 shapes (rectangle, square, circle) that the user can choose from, and when they choose one, a randomly-sized rectangle, square, or circle should appear in the GUI.
I guess I'm just having trouble figuring out where and how to implement the list selection listeners.
Here is my code so far:
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
public class ShapeSelectionWindow extends JPanel implements ListSelectionListener{
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
width = (int)Math.floor(Math.random()*250) + 50;
height = (int)Math.floor(Math.random()*250) + 50;
x = (int)Math.floor((615 - width) / 2);
y = (int)Math.floor((661 - height) / 2);
g.fillRect(x, y, width, height);
}
public static void main(String[] args) {
ShapeSelectionWindow ssw = new ShapeSelectionWindow();
JFrame jf = new JFrame();
JPanel shapeListPanel = new JPanel();
shapeListPanel.setBackground(Color.WHITE);
DefaultListModel<String> dlm = new DefaultListModel<String>();
dlm.addElement("Rectangle");
dlm.addElement("Square");
dlm.addElement("Circle");
JList<String> shapeList = new JList<String>(dlm);
shapeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
shapeListPanel.add(shapeList);
jf.getContentPane().setLayout(new BorderLayout());
jf.getContentPane().add(ssw, BorderLayout.CENTER);
jf.getContentPane().add(shapeListPanel, BorderLayout.EAST);
jf.setTitle("Simple Drawing GUI");
jf.setSize(700, 700);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
}
}
The current paintComponent method is for painting a rectangle. Like I said, I'm not sure how to implement the list selection listeners for this project in order to produce different shapes based on the user's selection.
Your current approach is placing too many eggs in a single basket. Why would ShapeSelectionWindow be responsible for managing the JList? It's sole responsibility is to draw a random shape.
Instead, you should break your design down.
I would start by defining a simple "shape" entity...
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
This just provides a limit set of options which can be used.
I would then update the "shape pane" to support these options...
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
The ShapePane doesn't care "how" the Shape is specified, it only cares when it changes and wants to paint it
I would then use another component to act as the primary controller between the JList and the ShapePane...
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
Runnable Example...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
}
I am trying to draw a circle in the center of a window, and I can't seem to get it right, should be really easy! My understanding is that if you set a JPanel as the content pane of a JFrame, the default layout is a flowLayout and that drawing should start from the top left of the screen as 0,0. To try and figure out what's going on I drew a blue background filling the JPanel, but it seems to have a margin like so:
When the window gets smaller than the blue rectangle, the drawing starts to get clipped from the opposite side:
What's going on! Here is my code:
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[])
{
Test test = new Test();
test.Start();
}
public void Start()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
this.setContentPane(circlePanel);
this.setVisible(true);
}
public class CirclePanel extends JPanel
{
private int radius = 200;
public void paintComponent(Graphics g) {
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getX(), getY(), diameter, diameter);
}
public int getX()
{
return (this.getWidth()/2) - radius;
}
public int getY()
{
return (this.getHeight()/2) - radius;
}
}
}
One big issue, you're unknowingly overriding two critical methods used by the layout managers to position components, the getX() and getY() methods, and thereby you're messing with the JPanel's placement.
So first and foremost, rename these methods so you don't accidentally move the JPanel.
Also, don't forget to call the super's paintComponent method, and avoid calling setSize(). Instead override getPreferredSize on your JPanel, and pack your JFrame.
e.g.,
public int getMyX() {
return myX;
}
public int getMyY() {
return myY;
}
For example
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[]) {
//!!
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test test = new Test();
test.Start();
}
});
}
public void Start() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
setContentPane(circlePanel);
pack();
setVisible(true);
}
public class CirclePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private int radius = 200;
public void paintComponent(Graphics g) {
super.paintComponent(g); //!!
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getMyX(), getMyY(), diameter, diameter);
}
//!!
public int getMyX() {
return (this.getWidth() / 2) - radius;
}
//!!
public int getMyY() {
return (this.getHeight() / 2) - radius;
}
//!!
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
}
The problem is that you're overriding getX() and getY(). Rename those to something else, and your code will work as expected. Also, it's a good idea to turn on compiler warnings for missing #Override annotations, and heed those warnings. (That would have notified the methods override superclass methods).
Try using this.add(circlePanel) instead if this.setContentPane(circlePanel) and set the size of the JPanel to be the same size as the JFrame