【问题标题】:High CPU usage in Custom JPasswordField自定义 JPasswordField 中的高 CPU 使用率
【发布时间】:2018-09-17 06:36:56
【问题描述】:

我创建了一个扩展 JPasswordField 的自定义 PasswordField。它工作正常。但问题是当我使用这个密码字段并运行 JFrame 时,这会消耗 HIGH CPU Usage。我只添加这个组件并运行它。但是当我使用 JButton 或 TextField 之类的另一个组件时,它工作正常并且 CPU 使用率正常。所以我需要知道如何解决这个问题,或者我的代码中是否存在占用 CPU 的问题。有谁能够帮我?提前致谢。

这是代码,

public class PasswordField extends JPasswordField implements ComponentListener
{
    private boolean materialMode = false;
    private Color borderColorNoFocus = MaterialColor.GREY_300;
    private Color borderColorFocus = new Color(0, 112, 192);
    private Dimension d = new Dimension(250, 42);
    private String placeholder = "";
    private Color phColor = new Color(0, 112, 192);
    private boolean band = true;
    private final JButton button = new JButton();
    private ImageIcon iconBlack = new ImageIcon(getClass().getResource("/Library/Images/visibleBlack.png"));
    private ImageIcon iconWhite = new ImageIcon(getClass().getResource("/Library/Images/visibleWhite.png"));
    private boolean xBlackIcon = false;
    private int btnHeight = this.d.height - 10;
    private boolean txtVisible = false;

    public PasswordField()
    {
        this.setEchoChar('*');
        this.setSize(this.d);
        this.setPreferredSize(this.d);
        this.setVisible(true);
        this.setMargin(new Insets(3, 6, 3, 6));

        this.setFont(Roboto.BOLD.deriveFont(14.0F));
        this.setForeground(new Color(0, 112, 192));
        this.button.setText("");
        this.button.setBorderPainted(false);
        this.button.setContentAreaFilled(false);
        this.button.setMargin(new Insets(2, 2, 2, 2));
        this.button.setVisible(true);
        this.button.setFocusPainted(false);
        this.button.setCursor(new Cursor(12));
        this.button.setBackground(new Color(0, 112, 192));
        this.add(this.button);
        this.setVisible(true);
        this.addComponentListener(this);
        this.setSelectionColor(this.button.getBackground());
        updateButton();

        this.getDocument().addDocumentListener(new DocumentListener()
        {
            @Override
            public void removeUpdate(DocumentEvent e)
            {
                PasswordField.this.band = (PasswordField.this.getText().length() <= 0);
            }

            @Override
            public void insertUpdate(DocumentEvent e)
            {
                PasswordField.this.band = false;
            }

            @Override
            public void changedUpdate(DocumentEvent de) {}
        });

        this.button.addMouseListener(new MouseListener()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if (PasswordField.this.txtVisible)
                {
                    ((JPasswordField)PasswordField.this.button.getParent()).setEchoChar('*');
                    PasswordField.this.iconBlack = new ImageIcon(getClass().getResource("/Library/Images/visibleBlack.png"));
                    PasswordField.this.iconWhite = new ImageIcon(getClass().getResource("/Library/Images/visibleWhite.png"));
                    PasswordField.this.txtVisible = false;
                }
                else
                {
                    ((JPasswordField)PasswordField.this.button.getParent()).setEchoChar('\000');
                    PasswordField.this.iconBlack = new ImageIcon(getClass().getResource("/Library/Images/invisibleBlack.png"));
                    PasswordField.this.iconWhite = new ImageIcon(getClass().getResource("/Library/Images/invisibleWhite.png"));
                    PasswordField.this.txtVisible = true;
                }
        ((JPasswordField)PasswordField.this.button.getParent()).requestFocus();
            }

            @Override
            public void mousePressed(MouseEvent e) {}

            @Override
            public void mouseReleased(MouseEvent e) {}

            @Override
            public void mouseEntered(MouseEvent e)
            {
                PasswordField.this.button.setOpaque(true);
                PasswordField.this.button.setIcon(PasswordField.this.xBlackIcon ? PasswordField.this.iconBlack : PasswordField.this.iconWhite);
            }

            @Override
            public void mouseExited(MouseEvent e)
            {
                PasswordField.this.button.setOpaque(false);
                PasswordField.this.button.setIcon(null);
            }
        });
        this.setPlaceholder("Password Field");
    }

    public boolean isxDarkIcon()
    {
        return this.xBlackIcon;
    }

    public void setxDarkIcon(boolean xDarkIcon)
    {
        this.xBlackIcon = xDarkIcon;
    }

    public Color getBotonColor()
    {
        return this.button.getBackground();
    }

    public void setBotonColor(Color botonColor)
    {
        this.button.setBackground(botonColor);
        setSelectionColor(this.button.getBackground());
    }

    public Color getBorderColorFocus()
    {
        return this.borderColorFocus;
    }

    public void setBorderColorFocus(Color borderColorFocus)
    {
        this.borderColorFocus = borderColorFocus;
    }

    public Color getBorderColorNoFocus()
    {
        return this.borderColorNoFocus;
    }

    public void setBorderColorNoFocus(Color borderColorNoFocus)
    {
        this.borderColorNoFocus = borderColorNoFocus;
    }

    public boolean isMaterialMode()
    {
        return this.materialMode;
    }

    public void setMaterialMode(boolean materialMode)
    {
        this.materialMode = materialMode;
    }

    private void updateBorder()
    {
        Border border = BorderFactory.createMatteBorder(0, 0, 2, 0, this.borderColorFocus);
        setBorder(BorderFactory.createCompoundBorder(border, 
                BorderFactory.createEmptyBorder(10, 10, 10, this.button.getSize().width + 5)));
    }

    private void updateButton()
    {
        this.btnHeight = (getSize().height - 10);
        this.button.setSize(new Dimension(this.btnHeight, this.btnHeight));
        this.button.setPreferredSize(new Dimension(this.btnHeight, this.btnHeight));

        this.button.setLocation(getWidth() - this.button.getWidth() - 5, 5);
        updateBorder();
    }

    @Override
    public void componentResized(ComponentEvent e)
    {
        updateButton();
    }

    @Override
    public void componentMoved(ComponentEvent e) {}

    @Override
    public void componentShown(ComponentEvent e) {}

    @Override
    public void componentHidden(ComponentEvent e) {}

    public void setPlaceholder(String placeholder)
    {
        this.placeholder = placeholder;
    }

    public String getPlaceholder()
    {
        return this.placeholder;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if (isMaterialMode())
        {
            if (isFocusOwner())
            {
                Border border = BorderFactory.createMatteBorder(0, 0, 2, 0, this.borderColorFocus);
                setBorder(BorderFactory.createCompoundBorder(border, 
                        BorderFactory.createEmptyBorder(10, 10, 10, this.button.getSize().width + 5)));

                this.phColor = getForeground();
            }
            else
            {
                Border border = BorderFactory.createMatteBorder(0, 0, 2, 0, this.borderColorNoFocus);
                setBorder(BorderFactory.createCompoundBorder(border, 
                        BorderFactory.createEmptyBorder(10, 10, 10, this.button.getSize().width + 5)));

                this.phColor = this.borderColorNoFocus;
            }
        }
        else
        {
            Border border = BorderFactory.createMatteBorder(0, 0, 2, 0, this.borderColorFocus);
            setBorder(BorderFactory.createCompoundBorder(border, 
                    BorderFactory.createEmptyBorder(10, 10, 10, this.button.getSize().width + 5)));
            this.phColor = getForeground();
        }

        g.setColor(new Color(this.phColor.getRed(), this.phColor.getGreen(), this.phColor.getBlue(), 90));

        g.drawString(this.band ? this.placeholder : "", 
        getMargin().left, 
        getSize().height / 2 + getFont().getSize() / 2);
    }
}

【问题讨论】:

  • 尝试从paintComponent() 方法中删除所有setBorder(...) 调用。 paintComponent 仅供绘画使用。
  • 您可以通过setMaterialMode 方法设置所有边框。此外,当您需要为焦点和非焦点状态设置不同的边框时,您还需要实现 focus listener
  • @SergiyMedvynskyy 如果你能给我一个示例代码,我真的很感激

标签: java swing jpasswordfield


【解决方案1】:

我已经在我的机器上复制了您的 java 代码并对其进行了调试。
我发现了为什么您的代码会导致 CPU 过高。

您在paintComponent() 方法中使用了setBorder() 方法,这是错误的,因为如果您查看父类中的setBorder() 方法,您会看到如果边框有此方法总是调用repaint()被改变了。 (这很正常)

因此,如果您在 paint() 方法中调用调用 repaint() 的东西,那么您将陷入无限循环。

paint() -> repaint() -> paint() -> repaint() -> paint().....

在您的代码中,您使用了setBorder 3 次。

如果您将setBorder 代码外包并从其他地方调用它,您可以解决这个问题。

【讨论】:

  • 我可能错了,但是重绘调用不是发布绘制事件而不是立即处理它们吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 2014-07-16
  • 2014-08-24
相关资源
最近更新 更多