Search code examples
javaswingjpanelpaintcomponentrepaint

Why doesn't repaint() work on my JPanel?


I've made my own subclass of JPanel, called SubPatternPanel. I want to use it in a frame to draw a grid, but when I call repaint() for the SubPatternPanel from the frame, it doesn't work.

When run, the frame is displayed with a "New" button. When New is pressed, a grid should be painted by my panel, but it isn't and I can't find the cause.

Below is the code for the SubPatternPanel:

package View;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;


public class SubPatternPanel extends JPanel
{

    public SubPatternPanel()
    {
    setLayout(null);
        setBackground(Color.white);
        setPreferredSize(new Dimension(240, 240));
    }

    @Override
    public void paintComponent(Graphics g)
    {   
    super.paintComponent(g);

    g.setColor(Color.black);

    for (int i = 0; i < 3; i++) 
    {
            for (int j = 0; j < 3; j++) 
        {
                g.drawLine(i * 80, j * 80, 240, j * 80);
                g.drawLine(i * 80, j * 80, i * 80, 240);
            }
        }
    }
}

Most of the frame code has been autogenerated, so I'm not sure what to leave out for a clearer picture.

package View;

import java.awt.BorderLayout;

public class PatternsMainFrame extends javax.swing.JFrame
{

    private SubPatternPanel subPatternPanel;

    public PatternsMainFrame()
    {
    initComponents();
    subPatternPanel = new SubPatternPanel();
    patternStartPanel.add(subPatternPanel, BorderLayout.CENTER);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents()
    {

        patternStartPanel = new javax.swing.JPanel();
        newButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout patternStartPanelLayout = new javax.swing.GroupLayout(patternStartPanel);
        patternStartPanel.setLayout(patternStartPanelLayout);
        patternStartPanelLayout.setHorizontalGroup(
            patternStartPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 277, Short.MAX_VALUE)
        );
        patternStartPanelLayout.setVerticalGroup(
            patternStartPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 278, Short.MAX_VALUE)
        );

        newButton.setText("New");
        newButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                newButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(patternStartPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 248, Short.MAX_VALUE)
                .addComponent(newButton)
                .addGap(112, 112, 112))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(patternStartPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(newButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }                      

    private void newButtonActionPerformed(java.awt.event.ActionEvent evt)                                          
    {
    subPatternPanel.repaint();
    }                                         

    public static void main(String args[])
    {
    try
    {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
        {
        if ("Nimbus".equals(info.getName()))
        {
            javax.swing.UIManager.setLookAndFeel(info.getClassName());
            break;
        }
        }
    } catch (ClassNotFoundException ex)
    {
        java.util.logging.Logger.getLogger(PatternsMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex)
    {
        java.util.logging.Logger.getLogger(PatternsMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex)
    {
        java.util.logging.Logger.getLogger(PatternsMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex)
    {
        java.util.logging.Logger.getLogger(PatternsMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }

    java.awt.EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
        new PatternsMainFrame().setVisible(true);
        }
    });
    }                    
    private javax.swing.JButton newButton;
    private javax.swing.JPanel patternStartPanel;                 
}

Solution

  • You should use setVisible(true) instead of repaint().

    repaint checks first whether visibility was set to true. repaint() is typically invoked when you want to repaint something that has already been painted once.