【问题标题】:JPanel gets paintComponent gets called when child is entered进入孩子时,JPanel 获取paintComponent 被调用
【发布时间】:2016-03-04 17:45:26
【问题描述】:

这里之前的一些条目提到了重复调用paintComponent(),但答案取决于paintComponent 本身调用repaint()。

使用 Nimbus L&F,如果我将 JPanel 子类化并添加 JButton 或 JTextField,那么每当我进入或离开孩子时,都会调用我的 JPanel 的 paintComponent() 方法。此外,如果 JTextField 获得焦点,我的面板的 paintComponent() 方法会在文本字段位置光标的每次闪烁时被调用。我的paintComponent() 方法除了打印它被调用之外什么都不做。这是一个例子:

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 );
         }
      } );
   }

}

当您单击第一个文本字段(嵌套在另一个 JPanel 中)时,您不会连续调用paintComponent()。但是,如果您单击第二个,您会不断接到电话。如果注释掉 Nimbus L&F 的设置,paintComponent() 就不会被重复调用。 JTextField 和 JButton 的 Nimbus 实现就像他们的 paintComponent 方法调用 parent.repaint() 一样。这是 Nimbus 中的错误,还是有意设计的?

【问题讨论】:

  • 我会说这很可能是设计使然(但不是故意的)。我可能需要处理一些可能正在发生的动画效果
  • 好吧,这是因为JTextField 是透明的,(isOpaque 返回false)。这意味着当 JTextField 被重绘时,RepaintManager 必须首先重绘父组件。每次更新插入符号时都会重新绘制JTextField。尝试添加t2.setOpaque(true); 看看会发生什么;)

标签: java swing nimbus-ios


【解决方案1】:

这似乎是 Nimbus 的设计选择。

如果您检查JTextField#isOpaque 的结果,它会返回false(使其透明)。这意味着当组件被重绘时,父容器也必须首先被重绘。

每次更新插入符号时,JTextField 都会触发重绘(闪烁)

您的第一个 JTextField 不会导致 Tester 重绘的原因是因为它位于一个不透明的容器中,所以只有它的直接父容器会被重绘。

尝试使 JTextField 不透明 (t2.setOpaque(true);) 看看会发生什么

【讨论】:

  • 是的,我现在看到了。 Nimbus 用圆角绘制这些组件,使其必须是透明的,以便在圆角边缘之外看到父级的背景。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多