JPanel gets paintComponent gets called when child is entered

大城市里の小女人 提交于 2020-01-05 17:38:05

问题


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?


回答1:


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



来源:https://stackoverflow.com/questions/34009631/jpanel-gets-paintcomponent-gets-called-when-child-is-entered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!