如何在自定义 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方法,光标会自动绘制。
我创建了一个圆角 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方法,光标会自动绘制。