这里的一些先前条目解决了反复调用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中的一个错误,还是按照设计的那种方式?
答案 0 :(得分:2)
这似乎是Nimbus的设计选择。
如果您检查JTextField#isOpaque
的结果,则返回false
(使其透明)。这意味着当重新绘制组件时,必须首先重新绘制父容器。
JTextField
每次更新插入符号时都会触发重新绘制(闪烁开启和关闭)
你的第一个JTextField
不会导致Tester
重绘的原因是因为它位于一个不透明的容器内,所以只有它的直接父容器才会被重新绘制。
尝试制作JTextField
不透明(t2.setOpaque(true);
),看看会发生什么