如何在自定义 JTextField 中绘制光标?

How can I draw a cursor in a custom JTextField?

我创建了一个圆角 JTextField,它覆盖了 paintComponent(g: Graphics) 方法。形状和文字绘制正确,但我还没有实现任何显示光标的东西。

How can I achieve that?

编辑: super.paintComponent(...) 不是解决方案。如果我使用它,那么你可以看到另一个绘制组件的边缘。

这是到目前为止的代码(没有描述任何渲染光标的内容!)

@Override
protected void paintComponent(Graphics g) {

    //TODO entfernen
    //super.paintComponent(g);

    if(g instanceof Graphics2D) {
        Graphics2D graphics = (Graphics2D) g;
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //Draw button background
        graphics.setColor(getBackground());
        graphics.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, arcRadius, arcRadius);

        this.paintText(graphics);

    }
}

protected final void paintText(@NotNull Graphics2D g) {
    //Draw font
    g.setColor(getForeground());
    if (this.getFont() != null && this.getText() != null) {
        FontMetrics fm = getFontMetrics(getFont());
        g.setColor(this.getForeground());
        g.drawString(this.getText(), ((this.getWidth() / 2) - (fm.stringWidth(this.getText()) / 2)),
                ((this.getHeight() / 2) + fm.getMaxDescent()));
    }
}

编辑 2: 这是结果,当我调用 super.paintComponent(...):

如你所见,超级组件可见。这就是为什么我不调用 super 方法的原因。

有人有使用 Carets 的经验吗?很确定这是正确的方法...

调用super.paintComponent(Graphics g)永远不会错!

与 OP 不同,我将提供一个最小的、可运行的示例,显示带有圆角的自定义 JTextField。

首先,这是我必须创建的 GUI。

如您所见,黄色的自定义 JTextField 具有圆角。

这是我所做的最小的可运行示例。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class CustomJTextField implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CustomJTextField());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Custom JTextField");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.setPreferredSize(new Dimension(400, 160));

        Font font = panel.getFont().deriveFont(32F);

        JLabel label = new JLabel("Something");
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setFont(font);
        panel.add(label, BorderLayout.BEFORE_FIRST_LINE);

        QTextField sampleField = new QTextField(panel, 10);
        sampleField.setBackground(Color.YELLOW);
        sampleField.setFont(font);
        panel.add(sampleField, BorderLayout.CENTER);

        frame.add(panel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class QTextField extends JTextField {

        private static final long serialVersionUID = 1L;

        private int arcRadius = 40;

        private Container container;

        public QTextField(Container container, int length) {
            super(length);
            this.container = container;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D graphics = (Graphics2D) g;
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // Draw button background
            graphics.setColor(container.getBackground());
            graphics.fillRect(0, 0, getWidth(), getHeight());
            graphics.setColor(getBackground());
            graphics.fillRoundRect(20, 20, getWidth() - 40, getHeight() - 40, arcRadius, arcRadius);

            this.paintText(graphics);

        }

        private void paintText(Graphics2D g) {
            // Draw font
            g.setColor(getForeground());
            if (this.getFont() != null && this.getText() != null) {
                FontMetrics fm = getFontMetrics(getFont());
                g.setColor(this.getForeground());
                g.drawString(this.getText(), ((this.getWidth() / 2) - (fm.stringWidth(this.getText()) / 2)),
                        ((this.getHeight() / 2) + fm.getMaxDescent()));
            }
        }
    }

}

好吧,我自己想出来了,真的很简单:

只需添加

this.getCaret().paint(g);

调用paintComponent方法,光标会自动绘制。