简体   繁体   中英

JPanel gets paintComponent gets called when child is entered

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 returns false (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 the Tester 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM