Some previous entries here address paintComponent() being called repeatedly, but the answers hinged on paintComponent itself calling repaint().
Using Nimbus L&F, if I subclass JPanel and add a JButton or JTextField, then my JPanel's paintComponent() method gets called whenever I enter or leave a child. In addition, if the JTextField gets focus, my panel's paintComponent() method gets called for every flash of the text field's position cursor. My paintComponent() method does nothing other than print that it is being called. Here's an example:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Tester extends JPanel {
public Tester() {
JPanel p = new JPanel();
JTextField t1 = new JTextField( "text in nested panel" );
p.add( t1 );
this.add( p );
JTextField t2 = new JTextField( "text" );
this.add( t2 );
JButton b = new JButton( "button" );
this.add( b );
setPreferredSize( new Dimension( 400, 200 ) );
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
System.out.println( "paint" );
}
public static void main( final String[] args ) {
SwingUtilities.invokeLater( new Runnable() {
@Override
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ( "Nimbus".equals( info.getName() ) ) {
UIManager.setLookAndFeel( info.getClassName() );
break;
}
}
} catch (Exception ex) {
System.out.println( "No Nimbus" );
}
final String name = new String( "GuiViewer" );
final JFrame jf = new JFrame( name );
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
final Tester comp = new Tester();
jf.add( comp );
jf.pack();
jf.setVisible( true );
}
} );
}
}
When you click in the first text field (nested inside another JPanel), you do not get continual calls to paintComponent(). But if you click in the second one, you continually get calls. If you comment out the setting of Nimbus L&F, the paintComponent() doesn't get repeated calls. The Nimbus implementation of JTextField and JButton act like their paintComponent method calls parent.repaint(). Is this a bug in Nimbus, or is it that way by design?
This seems to be a design choice of Nimbus.
If you inspect the result of
JTextField#isOpaque
, it returnsfalse
(making it transparent). This means that when ever the component is repainted, the parent container must first be repainted as well.The
JTextField
is triggering a repaint each time the caret is updated (blinks on and off)The reason why your first
JTextField
doesn't cause a repaint on theTester
is because it's sitting inside a opaque container, so only it's immediate parent container will be repainted.Try making the
JTextField
opaque (t2.setOpaque(true);
) and see what happens