Reputation: 7
I'm trying to draw an oval on a JFrame using Graphics2D, I want it to resize with the window which technically it does, it just not drawing about a 3rd of the oval. It's definitely something I'm doing wrong, I'm new to the Graphics2D part of Java.
I wasn't sure if it was my computer so I have tried running my code on a different PC to have it happen again so I'm not sure where I've gone wrong.
import javax.swing.*;
import java.awt.*;
public class ClockViewer {
public static void main(String[] args) {
//create frame
JFrame frame = new JFrame();
final int Frame_Width = 110;
final int Frame_Height = 130;
//set frame attributes
frame.setSize(Frame_Width, Frame_Height);
frame.setTitle("A Really Descriptive Title...");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//get pane attributes
System.out.println(frame.getContentPane().getWidth());
System.out.println(frame.getContentPane().getHeight());
//create ellipse
EllipseComponent ellipse = new EllipseComponent();
//add ellipse to frame
while(frame.getContentPane().getHeight() > 0 && frame.getContentPane().getWidth() > 0) {
int posX = Math.round(frame.getContentPane().getWidth() / 100) * 20;
int posY = Math.round(frame.getContentPane().getHeight() / 100) * 20;
int Width = Math.round(frame.getContentPane().getWidth() / 100) * 80;
int Height = Math.round(frame.getContentPane().getHeight() / 100) * 80;
ellipse.setAll(posX, posY, Width, Height);
frame.add(ellipse);
}
}
}
This is the next file:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public class EllipseComponent extends JComponent {
//global variables for ellipse drawing
int posX = 0;
int posY = 0;
int Width = 0;
int Height = 0;
//getters for getting variables values
public int getPosX() {
return this.posX;
}
public int getPosY() {
return this.posY;
}
@Override
public int getWidth() {
return this.Width;
}
@Override
public int getHeight() {
return this.Height;
}
//setters for setting variable values
public void setPosX(int newPosX) {
this.posX = newPosX;
}
public void setPosY(int newPosY) {
this.posY = newPosY;
}
public void setWidth(int newWidth) {
this.Width = newWidth;
}
public void setHeight(int newHeight) {
this.Height = newHeight;
}
//setter for all variables
public void setAll(int newPosX, int newPosY, int newWidth, int newHeight) {
this.posX = newPosX;
this.posY = newPosY;
this.Width = newWidth;
this.Height = newHeight;
}
//paint ellipse using graphics
@Override
public void paint(Graphics g) {
Graphics g2 = (Graphics2D) g;
g2.drawOval(posX, posY, Width, Height);
}
}
Thanks for any help you all can provide me ^^
Edit: I'm getting these errors if it helps:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: No such child: 0
at java.awt.Container.getComponent(Container.java:336)
at javax.swing.JComponent.rectangleIsObscured(JComponent.java:4390)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Upvotes: 0
Views: 139
Reputation: 6808
I am not getting the error you get. However, this is not the right way to do custom painting in Swing. I suggest you to take a look on how to perform custom painting. Long story short though, this thing you are trying with the while
condition will not work. Instead, let the component to be painted according to its parent size and coordinates without having to set them explicit :
/**
* @Overide paint method was a thing in AWT.
* In Swing you must override paintComponent (and call super.paintComponent())
* in order to respect the paint chain.
*
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (getParent() != null) { //Paint according to parent
Graphics g2 = (Graphics2D) g;
//Calculations
int posX = Math.round(getParent().getWidth() / 100) * 20;
int posY = Math.round(getParent().getHeight() / 100) * 20;
int Width = Math.round(getParent().getWidth() / 100) * 80;
int Height = Math.round(getParent().getHeight() / 100) * 80;
g2.drawOval(posX, posY, Width, Height);
}
}
Another not necessary thing you did is this:
@Override
public int getWidth() {
return this.Width;
}
Overriding getWidth
and getSize
of a component would not lead you anywhere.
Other useful links I recommend you to read are the Initial Threads and Why shouldn't I call setVisible(true) before adding components?
The full example:
public class ClockViewer {
public static void main(String[] args) {
SwingUtilities.invokeLater(()->{
// create frame
JFrame frame = new JFrame();
final int Frame_Width = 110;
final int Frame_Height = 130;
// set frame attributes
frame.setSize(Frame_Width, Frame_Height);
frame.setTitle("A Really Descriptive Title...");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// get pane attributes
System.out.println(frame.getContentPane().getWidth());
System.out.println(frame.getContentPane().getHeight());
// create ellipse
JComponent ellipse = new JComponent() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (getParent() != null) { //Paint according to parent
Graphics g2 = (Graphics2D) g;
//Calculations
int posX = Math.round(getParent().getWidth() / 100) * 20;
int posY = Math.round(getParent().getHeight() / 100) * 20;
int Width = Math.round(getParent().getWidth() / 100) * 80;
int Height = Math.round(getParent().getHeight() / 100) * 80;
g2.drawOval(posX, posY, Width, Height);
}
}
};
frame.add(ellipse);
frame.setVisible(true);
});
}
}
Upvotes: 1