Search code examples
javaswingcustom-painting

Can't draw line(method: paintComponent) - Java


I'm trying to draw a line in a JFrame, but line isn't drawn.

I tried to use the method setOpaque(true) for contentPane, lblNewLabel and l but nothing changed. I also tried call repaint(); outside this class but the situation is still the same. Here's the code:

public class DrawingClass extends JFrame
{
    private JPanel contentPane;
    public DrawingClass(int n, int s, int p) {
        Line l= new Line();
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setBounds(700, 300, 480, 640);
        contentPane = new JPanel();
        contentPane.setOpaque(true);
        setResizable(false);
        setContentPane(contentPane);
        contentPane.setLayout(null);
        JLabel lblNewLabel = new JLabel("");
        lblNewLabel.setIcon(new ImageIcon("image.png"));
        lblNewLabel.setBounds(0, 0, 480, 640);
        contentPane.add(lblNewLabel);
        l.setBounds(0,0,480,640);
        contentPane.add(l);
        repaint();
    }

    class Line extends JPanel
    {
        public void paintComponent(Graphics g) {
            g.setColor(Color.BLUE);
            g.fillRect(10, 10, 15, 12);
        }
    }
}

I expect a little line on the top left of the JFrame, above the background wallpaper, but nothing happen. It shows only the wallpaper.


Solution

  • There are several errors in your code:

    1. You're extending JFrame but you're not changing its behavior, so why are you doing that? JFrame is a rigid component, so it's never a good idea to extend from it, build your GUI based on JPanels instead. See: Extends JFrame vs. creating it inside the program

    2. Don't explicitly set the size of the JFrame, call pack() on it and instead override getPreferredSize from the JPanel, see: Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?

    3. You don't need to call setOpaque(...) in this case.

    4. Don't use a null-layout, it might lead to strange errors, because null Layout is Evil and frowned upon

    5. We don't have access to your image so we cannot test the ImageIcon and it's also not related to your question. However you should load your images as resources

    6. Don't explicitly set the bounds of each element, this is related to point (4) and you should use a Layout Manager or combinations of them to get your desired GUI.

    7. Don't call repaint() that way, it has no effect, it is supposed to repaint your UI when there's a change in it. However there is no change at the start of your program.

    8. You're breaking the paint-chain by not calling super.paintComponent(...) inside your paintComponent(...) method. Check the Tutorial on Custom Painting in Swing so that you learn how to do it properly

    9. And be careful, as paintComponents(...) (With a trailing s) is different from paintComponent(...) (Look at your title)

    So, after doing all of the above changes, we get to this simple program:

    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    
    public class DrawingClass {
        private JPanel contentPane;
        private JFrame frame;
        public static void main(String args[]) {
            SwingUtilities.invokeLater(() -> new DrawingClass().createAndShowGUI());
        }
    
        public void createAndShowGUI() {
            frame = new JFrame(getClass().getSimpleName());
            Line line = new Line();
            frame.add(line);
    
            frame.setResizable(false);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        }
    
        class Line extends JPanel {
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.BLUE);
                g.fillRect(10, 10, 15, 12);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(480, 640);
            }
        }
    }
    

    Which produces the following output:

    enter image description here