【问题标题】:How can I draw a cursor in a custom JTextField?如何在自定义 JTextField 中绘制光标?
【发布时间】:2020-07-11 06:42:59
【问题描述】:

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

我怎样才能做到这一点?

编辑: 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(g) 作为你的 paintComponent 方法的第一行。否则,是时候在 Javadoc 中搜索 JTextField。
  • 您是否希望有人发布完整的代码解决方案,说明如何创建圆角 JTextField,或者您需要帮助来纠正您的代码?如果是后者,那么我建议您edit您的问题并发布您的代码。如果是前者,那我怀疑这会发生。
  • @GilbertLeBlanc:你猜对了。事实上它已经被注释掉了
  • 调用 super 是错误的!绘制了第二个按钮,该按钮显示在自定义按钮的圆角中。
  • 也许以下会有帮助? Painting in AWT and SwingPerforming Custom Painting

标签: java swing jtextfield caret


【解决方案1】:

嗯,我自己想通了,这很容易:

只需添加

this.getCaret().paint(g);

到paintComponent方法,然后光标将被自动绘制。

【讨论】:

    【解决方案2】:

    调用 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()));
                }
            }
        }
    
    }
    

    【讨论】:

    • 是的,我知道。我完全改变了这一点。超级按钮仍然可见并且足够有趣,光标在您的自定义按钮中也不可见。这是为什么呢?
    • @F_Schmidt:您将不得不自己获取插入符号的位置并绘制光标。您强制进入文本字段的中心让我感到惊讶。这些家伙所做的一切,你都必须做。 developer.classpath.org/doc/javax/swing/JTextField-source.html
    • 天哪。那是我所期望的。您知道如何绘制光标吗?我不知道从哪里开始。
    猜你喜欢
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    相关资源
    最近更新 更多