Search code examples
javaswinggraphics2dpaintcomponent

Drawing an object using getGraphics() without extending JFrame


How can I draw an object without a class (which extends JFrame)? I found getGraphics method but it doesnt draw the object.

import javax.swing.*;
import java.awt.*;
public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setSize(600, 400);

        JPanel panel = new JPanel();
        frame.add(panel);

        Graphics g = panel.getGraphics();
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, 100, 100);
    }
}

Solution

  • If you want to change the way your component is being drawn (you are adding rectangles), you need to redefine paintComponent() in that component. In your code, you are using getGraphics().

    You shouldn't call getGraphics() on a component. Any painting you do (to the Graphics returned) will be temporary and will be lost the next time Swing determines a component needs to be repainted.

    Instead, you should override the paintComponent(Graphics) method (of the JComponent or JPanel), and do the painting in this method, using the Graphics object received as argument.

    Check this link for further reading.

    Below is your code, corrected.

    import javax.swing.*;
    import java.awt.*;
    
    public class Main {
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            frame.setSize(600, 400);
    
            JPanel panel = new JPanel() {
                @Override
                public void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    g.setColor(Color.BLUE);
                    g.fillRect(0, 0, 100, 100);
                }
            };
            frame.add(panel);
    
            // Graphics g = panel.getGraphics();
            // g.setColor(Color.BLUE);
            // g.fillRect(0, 0, 100, 100);
    
            frame.validate(); // because you added panel after setVisible was called
            frame.repaint(); // because you added panel after setVisible was called
        }
    }
    

    Another version, does the exact same thing, but may be clearer to you:

    import javax.swing.*;
    import java.awt.*;
    
    public class Main {
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            frame.setSize(600, 400);
    
            JPanel panel = new MyRectangleJPanel(); // changed this line
            frame.add(panel);
    
            // Graphics g = panel.getGraphics();
            // g.setColor(Color.BLUE);
            // g.fillRect(0, 0, 100, 100);
    
            frame.validate(); // because you added panel after setVisible was called
            frame.repaint(); // because you added panel after setVisible was called
        }
    }
    
    /* A JPanel that overrides the paintComponent() method and draws a rectangle */
    class MyRectangleJPanel extends JPanel {
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.BLUE);
            g.fillRect(0, 0, 100, 100);
        }
    }