[英]paintComponent() TextField causes Infinite loop (itself + parent)
After several days of research, I beg to ask your help. 经过几天的研究,我请求您的帮助。 The following code works but generates significant CPU consumption.
以下代码有效,但会产生大量的CPU消耗。 It seems that this simple text field executes "paintComponent" in a loop, not only its own, but also its parent (JPanel).
看起来,这个简单的文本字段循环执行“ paintComponent”,不仅是其自身,还包括其父级(JPanel)。 Could you give me a way to correct that?
您能给我一种纠正方法吗?
Thank you :) 谢谢 :)
package view;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JTextField;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import constants.Colors;
import constants.Polices;
import constants.Spacing;
public class FieldText extends JTextField
{
private static final long serialVersionUID = 4526307090633268880L;
private int xheight = 96;
public Boolean hinted = false; // Définit si le contenu == au hint ou si le contenu a été entré par l'utilisateur.
protected Color bgColor = Colors.INPUT; // Background normal.
protected Color textColor = Colors.TEXT_INPUT; // Couleur du texte normal.
protected Color bgHinted = Colors.INPUT; // Background lors que le placeholder est actif.
protected Color textHinted = Colors.TEXT_INPUT; // Couleur du texte placeholder.
protected Font textFont = Polices.INPUTS; // Police texte utilisateur.
protected Font textHintFont = Polices.INPUTS_HINT; // Police placeholder.
public FieldText()
{
super();
init(null, null);
}
/**
* @param text String Texte du champ (valeur)
* @param text String PlaceHoler
*/
public FieldText( String text, String hint )
{
super();
init(text, hint);
}
/**
* @param hint Sting Texte du champ (valeur).
*/
public FieldText( String hint )
{
super();
init(null, hint);
}
private void init( String text, String hint )
{
setOpaque(false);
setBackground(bgColor);
setForeground(textColor);
setMinimumSize( new Dimension( 200, 64 ) );
setBorder( new CompoundBorder (
BorderFactory.createMatteBorder(0, 5, 0, 0, Colors.GREEN),
new EmptyBorder( Spacing.PADDING_INPUTS )
)
);
setFont( Polices.INPUTS );
if ( text != null && text.length() > 0 )
{
setText(text);
}
setHeight(-1); // Height by default.
}
/**
* Définit la hauteur de l'élément.
* @param height int Hauteur à attribuer à l'élément. -1 pour utiliser la hauteur par défaut (xheight).
*/
public void setHeight( int height )
{
setPreferredSize( new Dimension(this.getWidth(), (height>-1) ? height : xheight) );
}
@Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
GradientPaint gp = new GradientPaint (
0, 0, new Color( 255, 255, 255, 50 ),
0, 20, new Color( 179, 179, 179, 50 )
);
g2d.setPaint( gp );
g2d.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 10, 10);
super.paintComponent(g2d);
System.out.println("======> inside FieldText.paintComponent() ");
}
}`
JTextField is in JPanel in JFrame. JTextField在JFrame的JPanel中。
Sorry for my bad english ... 对不起,我的英语不好 ...
Here a little example who causes the loop. 这里是一个引起循环的小例子。
EDIT : Exemple integration in src/views/GuestLoginView 编辑:在src / views / GuestLoginView中的示例集成
Running your program doesn't cause high CPU consumption for me. 运行程序不会对我造成很高的CPU消耗。
Also the TextField probably needs constant repainting to animate the blinking cursor. 同样,TextField可能需要不断重绘以动画闪烁的光标。 One repaint every second is a reasonable expectation and it is what I see on my console.
每秒进行一次重绘是一个合理的期望,这就是我在控制台上看到的。
I rewrote your code more concisely to put it (mostly) in one file to simplify this. 我更简洁地重写了您的代码,以将其(大部分)放在一个文件中以简化此过程。 First, the constant repainting is caused by the blinking of insertion carat.
首先,不断重涂是由插入克拉的闪烁引起的。 But to do what you want you with the
gradientPaint
it is best to use JLayer
. 但是,要使用
gradientPaint
,最好使用JLayer
。 A couple other things to facilitate your code. 还有其他一些事情可以简化您的代码。
init()
called by the constructor, simply have multiple constructors call the main constructor using this
. init()
,只需让多个构造函数使用this
调用主构造函数即可。 Like this(null, null)
this(null, null)
JLayer
allows Swing components to draw on their children. JLayer
允许Swing组件利用其子代。 This is exactly what you want to do in your program. 这正是您要在程序中执行的操作。 I have included this link so you can see the tutorial and the accompanying video.
我已经包含了此链接,因此您可以观看教程和随附的视频。 I used the names of the field that were in the video to help follow the explanation in your own code.
我使用视频中的字段名称来帮助按照您自己的代码中的说明进行操作。 And finally, when I ran this I did not see but a
2% CPU
utilization over all of my processes on Windows 10 with a quad core i7 processor
. 最后,当我运行此程序时,我没有看到
Windows 10 with a quad core i7 processor
上所有进程的2% CPU
利用率只有2% CPU
。
package view;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.LayerUI;
import constants.Colors;
import constants.Polices;
import constants.Spacing;
public class TestFrame {
private static final long serialVersionUID = 818148271075948079L;
private TestPanel panelContent;
private FieldText field1, field2;
JFrame frame = new JFrame();
public TestFrame() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
field1 = new FieldText("your text 1", null);
field2 = new FieldText("your text 2", null);
panelContent = new TestPanel();
panelContent.add(field1);
panelContent.add(field2);
LayerUI<JComponent> layerUI = new MyLayerUISubClass();
JLayer<JComponent> jlayer = new JLayer<>(panelContent, layerUI);
panelContent.setPreferredSize(new Dimension(500, 256));
frame.add(jlayer);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new TestFrame();
}
}
class MyLayerUISubClass extends LayerUI<JComponent> {
@Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
Graphics2D g2d = (Graphics2D) g.create();
GradientPaint gp = new GradientPaint(0, 0, new Color(255, 255, 255, 50),
0, 20, new Color(179, 179, 179, 50));
g2d.setPaint(gp);
// g2d.fillRect(0, 0, c.getWidth() - 1, c.getHeight() - 1);
g2d.fillRoundRect(0, 0, c.getWidth() - 1, c.getHeight() - 1, 10, 10);
System.out.println("======> inside FieldText.paintComponent() ");
g2d.dispose();
}
}
class TestPanel extends JPanel {
private static final long serialVersionUID = -4236642932453746731L;
public TestPanel() {
setLayout(new GridLayout(2, 1));
setBackground(Color.black);
}
@Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
System.out.println("======> inside TestPanel.paintComponent() ");
}
}
class FieldText extends JTextField {
private static final long serialVersionUID = 4526307090633268880L;
private int xheight = 96;
public Boolean hinted = false; // Définit si le contenu == au hint ou si le contenu a été entré par
// l'utilisateur.
protected Color bgColor = Colors.INPUT; // Background normal.
protected Color textColor = Colors.TEXT_INPUT; // Couleur du texte normal.
protected Color bgHinted = Colors.INPUT; // Background lors que le placeholder est actif.
protected Color textHinted = Colors.TEXT_INPUT; // Couleur du texte placeholder.
protected Font textFont = Polices.INPUTS; // Police texte utilisateur.
protected Font textHintFont = Polices.INPUTS_HINT; // Police placeholder.
public FieldText(String text, String hint) {
setOpaque(true);
setBackground(bgColor);
setForeground(textColor);
setMinimumSize(new Dimension(200, 64));
setBorder(new CompoundBorder(
BorderFactory.createMatteBorder(0, 5, 0, 0, Colors.GREEN),
new EmptyBorder(Spacing.PADDING_INPUTS)));
setFont(Polices.INPUTS);
if (text != null && text.length() > 0) {
setText(text);
}
setHeight(-1); // Height by default.
}
public FieldText() {
this(null, null);
}
public FieldText(String hint) {
this(null, hint);
}
/**
* Définit la hauteur de l'élément.
*
* @param height
* int Hauteur à attribuer à l'élément. -1 pour utiliser la hauteur par
* défaut (xheight).
*/
public void setHeight(int height) {
setPreferredSize(new Dimension(this.getWidth(), (height > -1) ? height
: xheight));
}
}
I found the problem. 我发现了问题。
It was not in the field, but in the paintComponent() of my custom button. 它不在字段中,而是在我的自定义按钮的paintComponent()中。
I had 我有
ImageIcon bicon = ( mouseHover ) ? new ImageIcon( iconHover ) : new ImageIcon( icon );
setIcon(bicon);
getIcon().paintIcon( this, g2, getIconX(), getIconY() );
==> setIcon in the paintComponent was not a good idea , it caused the loop and CPU usage. ==> paintComponent中的setIcon 不是一个好主意 ,它导致了循环和CPU使用率。
Thank you for your useful advices. 感谢您的有用建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.