I'e been learning java for a while and I've just started a project to make a functional drawing program. However the code below is supposed to draw a rectangle on a bufferedimage but it does not work.
Code for drawing rectangle
public class DrawRectangle extends Panel {
public void drawRect(int x, int y, int width, int height) {
System.out.println("new Rectangle = X:" + x + " Y:" + y + " Width:" + width + " height:" + height);
canvas.createGraphics().draw(new Rectangle2D.Double(x, y, width, height));
}}
public class Panel extends JPanel {
BufferedImage canvas = new BufferedImage(400,400, BufferedImage.TYPE_INT_ARGB);
......
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Repainting");
g.drawImage(canvas, 25, 25, null);
}}
Note: All the methods are going off correctly so it is not simply me neglecting to initiate drawRectangle()
Edit my bad: you're not setting color properly. To wit:
e.g.,
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.swing.*;
public class FunnyDraw {
private static void createAndShowGui() {
DrawRectangle mainPanel = new DrawRectangle();
mainPanel.drawRect(10, 10, 100, 100);
mainPanel.betterDrawRect(200, 200, 200, 200);
JFrame frame = new JFrame("FunnyDraw");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class HisPanel extends JPanel {
private static final Color COLOR = Color.black;
private static final int PREF_W = 600;
private static final int PREF_H = 450;
protected BufferedImage canvas = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Repainting");
g.drawImage(canvas, 25, 25, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void draw(Shape shape) {
Graphics2D g2 = canvas.createGraphics();
g2.setColor(COLOR);
g2.draw(shape);
g2.dispose();
repaint();
}
}
class DrawRectangle extends HisPanel {
public void drawRect(int x, int y, int width, int height) {
Graphics2D g2 = canvas.createGraphics();
g2.setColor(Color.black);
g2.draw(new Rectangle2D.Double(x, y, width, height));
g2.dispose();
repaint();
}
public void betterDrawRect(int x, int y, int width, int height) {
draw(new Rectangle2D.Double(x, y, width, height));
}
}
Related
The program draws completely fine if the border layout is Center, but not for any other direction. Here is the code below.
public class MainVisualizer {
public static void main(String[] args) {
int windowWidth = 1000;
int windowHeight = 850;
JFrame mainFrame = new JFrame("Plotter and Integration Visualizer ");
mainFrame.setSize(windowWidth, windowHeight);
mainFrame.add(new GraphComponent(windowWidth, windowHeight), BorderLayout.EAST);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
}
}
public class GraphComponent extends JComponent {
private ArrayList<String> textFunctions;
private int frameWidth;
private int frameHeight;
public GraphComponent(int width, int height) {
this.textFunctions = new ArrayList<>();
this.frameHeight = height;
this.frameWidth = width;
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.drawLine(0, frameHeight/2, frameWidth, frameHeight/2);//X axis
g2.drawLine(frameWidth/2, 0, frameWidth/2, frameHeight);//Y axis
System.out.println( this.getX()+" "+ this.getY());
g2.drawString("X", frameWidth/2, frameHeight/2);
}
}
I believe what you are seeing is because you haIven't set preferred size. The default is 0, and so that's what you get when you add not to the center
public class GraphComponent extends JComponent {
private ArrayList<String> textFunctions;
private int frameWidth;
private int frameHeight;
public GraphComponent(int width, int height) {
this.textFunctions = new ArrayList<>();
this.frameHeight = height;
this.frameWidth = width;
//Set preferredSize right here
setPreferredSize(new Dimension(width, height));
///////////////
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.drawLine(0, frameHeight/2, frameWidth, frameHeight/2);//X axis
g2.drawLine(frameWidth/2, 0, frameWidth/2, frameHeight);//Y axis
System.out.println( this.getX()+" "+ this.getY());
g2.drawString("X", frameWidth/2, frameHeight/2);
}
}
I need to draw a ring, with given thickness, that looks something like this:
The center must be transparent, so that it doesn't cover previously drawn shapes. (or other rings) I've tried something like this:
//g is a Graphics2D object
g.setColor(Color.RED);
g.drawOval(x,y,width,height);
g.setColor(Color.WHITE);
g.drawOval(x+thickness,y+thickness,width-2*thickness,height-2*thickness);
which draws a satisfactory ring, but it covers other shapes; the interior is white, not transparent. How can I modify/rewrite my code so that it doesn't do that?
You can create an Area from an Ellipse2D that describes the outer circle, and subtract the ellipse that describes the inner circle. This way, you will obtain an actual Shape that can either be drawn or filled (and this will only refer to the area that is actually covered by the ring!).
The advantage is that you really have the geometry of the ring available. This allows you, for example, to check whether the ring shape contains a certain point, or to fill it with a Paint that is more than a single color:
Here is an example, the relevant part is the createRingShape method:
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RingPaintTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RingPaintTestPanel p = new RingPaintTestPanel();
f.getContentPane().add(p);
f.setSize(800,800);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class RingPaintTestPanel extends JPanel
{
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.RED);
g.drawString("Text", 100, 100);
g.drawString("Text", 300, 100);
Shape ring = createRingShape(100, 100, 80, 20);
g.setColor(Color.CYAN);
g.fill(ring);
g.setColor(Color.BLACK);
g.draw(ring);
Shape otherRing = createRingShape(300, 100, 80, 20);
g.setPaint(new GradientPaint(
new Point(250, 40), Color.RED,
new Point(350, 200), Color.GREEN));
g.fill(otherRing);
g.setColor(Color.BLACK);
g.draw(otherRing);
}
private static Shape createRingShape(
double centerX, double centerY, double outerRadius, double thickness)
{
Ellipse2D outer = new Ellipse2D.Double(
centerX - outerRadius,
centerY - outerRadius,
outerRadius + outerRadius,
outerRadius + outerRadius);
Ellipse2D inner = new Ellipse2D.Double(
centerX - outerRadius + thickness,
centerY - outerRadius + thickness,
outerRadius + outerRadius - thickness - thickness,
outerRadius + outerRadius - thickness - thickness);
Area area = new Area(outer);
area.subtract(new Area(inner));
return area;
}
}
You can use the Shape and Area classes to create interesting effects:
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
import java.net.*;
public class Subtract extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int size = 100;
int thickness = 10;
int innerSize = size - (2 * thickness);
Shape outer = new Ellipse2D.Double(0, 0, size, size);
Shape inner = new Ellipse2D.Double(thickness, thickness, innerSize, innerSize);
Area circle = new Area( outer );
circle.subtract( new Area(inner) );
int x = (getSize().width - size) / 2;
int y = (getSize().height - size) / 2;
g2d.translate(x, y);
g2d.setColor(Color.CYAN);
g2d.fill(circle);
g2d.setColor(Color.BLACK);
g2d.draw(circle);
g2d.dispose();
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Subtract");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Subtract());
frame.setLocationByPlatform( true );
frame.setSize(200, 200);
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Using an Area you can also add multiple Shapes together or get the intersection of multiple Shapes.
You could use graphics.setStroke(...) for this. This way the center will be fully transparent and therefore won't cover previously drawn shapes. In my example I had to do some additional calculations because of this method though, to make sure the displayed x and y coordinates are actually the same as the ones of the Ring instance:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example {
public Example() {
ArrayList<Ring> rings = new ArrayList<Ring>();
rings.add(new Ring(10, 10, 100, 20, Color.CYAN));
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gg = (Graphics2D) g.create();
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Ring ring : rings) {
// Previously drawn
gg.setColor(Color.BLACK);
String str = "Hello!";
gg.drawString(str, ring.getX() + (ring.getWidth() - gg.getFontMetrics().stringWidth(str)) / 2,
ring.getY() + ring.getHeight() / 2 + gg.getFontMetrics().getAscent());
// The actual ring
ring.draw(gg);
}
gg.dispose();
}
};
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
class Ring {
private int x, y, width, height, thickness;
private Color color;
public Ring(int x, int y, int width, int height, int thickness, Color color) {
setX(x);
setY(y);
setWidth(width);
setHeight(height);
setThickness(thickness);
setColor(color);
}
public Ring(int x, int y, int radius, int thickness, Color color) {
this(x, y, radius * 2, radius * 2, thickness, color);
}
public void draw(Graphics2D gg) {
Stroke oldStroke = gg.getStroke();
Color oldColor = gg.getColor();
gg.setColor(Color.BLACK);
gg.setStroke(new BasicStroke(getThickness()));
gg.drawOval(getX() + getThickness() / 2, getY() + getThickness() / 2, getWidth() - getThickness(),
getHeight() - getThickness());
gg.setColor(getColor());
gg.setStroke(new BasicStroke(getThickness() - 2));
gg.drawOval(getX() + getThickness() / 2, getY() + getThickness() / 2, getWidth() - getThickness(),
getHeight() - getThickness());
gg.setStroke(oldStroke);
gg.setColor(oldColor);
}
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;
}
public int getThickness() {
return thickness;
}
public void setThickness(int thickness) {
this.thickness = thickness;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
I want to make JTextArea has a rounded corners, and i did this code :
public BPosTxtArea() {
super();
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}
but it still has a square border outside like picture bellow :
Can anyone help me?
Start by having a look at How to Use Borders
This is a very simple example:
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JTextArea ta = new JTextArea(10, 20);
ta.setBorder(new RoundBorder(20));
JScrollPane sp = new JScrollPane(new JTextArea(10, 20));
sp.setBorder(new RoundBorder(20));
add(ta, gbc);
add(sp, gbc);
}
}
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
}
Problems, the border is painted "within" the component fill area, meaning that the corners will be the same color as the fill area. There's no way around it using Border.
The trick would be to create a second component, onto which you could paint the border (via the paintComponent, filling the area within the border the same color as the text area) and then add the component into that.
Updated
Based on you code example, you're not overriding getInsets, which is going to be very important, the other thing is, it appears that your JTextArea is within a JScrollPane...
public class BPosTextArea extends JTextArea {
private int radius;
public BPosTextArea() {
super(10, 20);
setOpaque(false);
setBorder(null);
setRadius(20);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
}
public void setRadius(int radius) {
this.radius = radius;
repaint();
}
public int getRadius() {
return radius;
}
#Override
public Insets getInsets() {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
}
A solution is to set the border to null for the JScrollPane
I am creating a simulation type application, I want one background layer and another layer on top for all of the animations. Im currently using JlayeredPanes but i cannot get the background on the top layer to show as transparent so I can see the background, any help is much appreciated, heres the code:
Background layer
public class SimBackground extends JLayeredPane{
private Model theModel;
private SimulationArea simulationArea;
public SimBackground(Model theModel){
this.theModel=theModel;
setBackground(new Color(0, 230, 0));
setOpaque(true);
setPreferredSize(new Dimension(500,500));
setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
for(int x=0;x<50;x++){
for(int y=0;y<50;y++){
g.drawRect((x*10), (y*10), 10, 10);
}
}
}
Top layer
public class SimulationArea extends JLayeredPane {
private int SPEED = 100;
private Model theModel;
Timer timer;
public SimulationArea(Model theModel){
this.theModel = theModel;
setPreferredSize(new Dimension(500,500));
setLocation(0,0);
setOpaque(false);
setBackground(new Color(0,0,0,0));
setVisible(true);
//Swing Timer
timer = new Timer(SPEED,new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
update();
repaint();
revalidate();
}
});
}
private void update() {
theModel.update();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
//test get 1 active object
ArrayList<ActiveObject> activeObjects = theModel.getActiveObjects();
//System.out.println(activeObjects.size());
for(int i=0; i<activeObjects.size(); i++){
ActiveObject activeObject = theModel.getActiveObjects().get(i);
int x = activeObject.getCoordinates().getX();
int y = activeObject.getCoordinates().getY();
int size = activeObject.getSize();
g2d.fillRect (x ,y , size, size);
}
}
Can someone please tell me what i'm missing here?
Don't use a JLayeredPane, but if you do need to use JLayeredPane in the future, you will want to read the tutorial here since as per my comment you're not using them correctly at all. Instead I recommend that you simplify by doing all drawing in a single JPanel, drawing your background into a BufferedImage perhaps in the constructor, and then drawing that image and your sprites within the JPanel's paintComponent method.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class SimExample extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private static final Color BKGD_COLOR = new Color(0, 230, 0);
private BufferedImage bkgrnd = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
public SimExample() {
Graphics2D g = bkgrnd.createGraphics();
g.setBackground(BKGD_COLOR);
g.clearRect(0, 0, PREF_W, PREF_H);
g.setColor(Color.black);
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
g.drawRect((x * 10), (y * 10), 10, 10);
}
}
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (bkgrnd != null) {
g.drawImage(bkgrnd, 0, 0, null);
}
// draw sprites here
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
SimExample mainPanel = new SimExample();
JFrame frame = new JFrame("SimExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I was reading Core Java and encountered this code snippet:
package draw;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class DrawTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new DrawFrame();
frame.setTitle("DrawTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class DrawFrame extends JFrame
{
public DrawFrame()
{
add(new DrawComponent());
pack();
}
}
class DrawComponent extends JComponent
{
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 400;
public void paintCompent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// draw a rectangle
double leftX = 100;
double topY = 100;
double width = 200;
double height = 150;
Rectangle2D rect = new Rectangle2D.Double(leftX, topY, width, height);
g2.draw(rect);
// draw the enclosed ellipse
Ellipse2D ellipse = new Ellipse2D.Double();
ellipse.setFrame(rect);
g2.draw(ellipse);
// draw a diagonal line
g2.draw(new Line2D.Double(leftX, topY, leftX + width, topY + height));
// draw a circle with the same center
double centerX = rect.getCenterX();
double centerY = rect.getCenterY();
double radius = 150;
Ellipse2D circle = new Ellipse2D.Double();
circle.setFrameFromCenter(centerX, centerY, centerX + radius, centerY + radius);
g2.draw(circle);
}
public Dimension getPreferredSize()
{
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
I tried this code on Eclipse, it did run but, instead of rectangles, ellipse, diagonal lines and circle, there appeared nothing in the frame. I double-checked the code against the book, there was no typo. What is wrong?
There's a spelling mistake...
public void paintCompent(Graphics g) {
should be
public void paintComponent(Graphics g) {
This is why you should use the #Override annotation, as it will give you a compile time error when you try to override a method that doesn't exist within the parent hierarcy.
You should also be calling super.paintComponent(g); before performing any custom painting