Search code examples
javaswinggraphicsgraphics2d

Why oval can't be drawn?


Im trying to understand a Paint Graphics, but my oval can't be drawn. Can someone tell me what am I doing wrong and oval is not drawing? Where did I make a mistake?

Main class:

import java.awt.EventQueue;
public class Main {
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            Frame frame = new Frame();

        }
    });
}

Frame class:

public class Frame extends JFrame {
private static final long serialVersionUID = 1L;

public static Grafika grafika;

public Frame() {
    JFrame frame = new JFrame("Title");
    grafika = new Grafika();

    frame.setSize(500, 500);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setLayout(null);
    // frame.addKeyListener(this);
    frame.add(grafika);
}
}

And last Grafic class:

public class Grafika extends JComponent {

int x = 200;
int y = 200;

public void paint(Graphics g) {

    Graphics2D oval = (Graphics2D) g;
    oval.setColor(Color.BLACK);
    oval.fillOval(x, y, 100, 100);
    oval.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
    RenderingHints.VALUE_ANTIALIAS_ON);

}
}

Solution

  • Several issues, but the biggest is that you're using a null layout on your JFrame, and then adding a JComponent whose preferred size and size are both 0,0. So while you're adding your Grafika to the JFrame, it doesn't have a chance of being displayed.

    Suggestions:

    • Never use null layout, except in very specific exceptional circumstances.
    • Give your Grafika component a preferred size, best by overriding getPreferredSize(), but at this stage, I think that it would be OK to call setPreferredSize(...) on it.
    • Add it to the JFrame, pack() the JFrame and then lastly, only after all components have been added to the JFrame, make it visible.

    Also

    • You should be overriding paintComponent not paint
    • You should call the super painting method within your override.
    • Always use the @Override annotation when you think that you're overriding a parent method. You could be wrong, and you want the compiler to tell you.
    • Set the RenderingHints before drawing. Else the hints will have no effect on the drawing.
    • Avoid giving your classes names that clash with the names of core Java classes, such as Frame. This will potentially confuse others and your future self.

    e.g.,

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    
    import javax.swing.*;
    
    public class MyGrafika extends JComponent {
        private static final int PREF_W = 500;
        private static final int PREF_H = PREF_W;
        private static final Color OVAL_COLOR = Color.RED;
        private int ovalX = 200;
        private int ovalY = 200;
        private int ovalWidth = 100;
        private int ovalHeight = 100;
    
        public MyGrafika() {
            setPreferredSize(new Dimension(PREF_W, PREF_H));
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(OVAL_COLOR);
            g2.fillOval(ovalX, ovalY, ovalWidth, ovalHeight);
        }
    
        private static void createAndShowGui() {
            MyGrafika mainPanel = new MyGrafika();
    
            JFrame frame = new JFrame("MyGrafika");
            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(() -> createAndShowGui());
        }
    }