简体   繁体   English

paintComponent()TextField导致无限循环(自身+父级)

[英]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中的示例集成

Here is the full src 这是完整的src

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. 还有其他一些事情可以简化您的代码。

  1. Don't extend JFrame. 不要扩展JFrame。 Its methods are rarely overridden so there is no need to do so. 它的方法很少被重写,因此没有必要这样做。 Just use an instance. 只需使用一个实例。
  2. Instead of using 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.

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