防止文字在边框对象后面

时间:2019-06-13 00:25:24

标签: java swing

我有一个JTextField,我想在右边显示一个验证图标,但是,如果文本足够长,它将在图标下运行:

text behind icon

在使图标显示在JTextField中时如何避免这种情况?

这是一个重现该问题的简单程序:


import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;

public final class Borders extends JFrame {

    public Borders() {
        JTextField field = new JTextField();
        Border outsideBorder = field.getBorder();
        field.setBorder(new CompoundBorder(outsideBorder, new AbstractBorder() {

            @Override
            public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
                Insets insets = outsideBorder.getBorderInsets(c);
                Font font = c.getFont();
                FontMetrics metrics = c.getFontMetrics(font);
                int by = (c.getHeight() / 2) + (metrics.getAscent() / 2) - insets.top;
                int bw = Math.max(2, insets.left); // border width
                int iw = metrics.stringWidth("=="); // icon width
                int bx = x + width - (Math.round(iw * 1.5f) + (bw * 2)) + 2;
                g.translate(bx, by);
                g.setColor(Color.RED);
                g.setFont(c.getFont().deriveFont(Font.BOLD, font.getSize()));
                g.drawString("==", x + (iw / 2), y);
            }

            @Override
            public boolean isBorderOpaque() {
                return true;
            }

        }));
        this.add(field);
        this.pack();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Borders().setVisible(true);
        });
    }

}

这是示例程序的结果:

enter image description here

生成第一张图片的代码在GitHub上。

1 个答案:

答案 0 :(得分:0)

您必须实现方法getBorderInsets。像这样:

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;

public final class Borders extends JFrame {

    public Borders() {
        JTextField field = new JTextField();
        Border outsideBorder = field.getBorder();
        field.setBorder(new CompoundBorder(outsideBorder, new AbstractBorder() {

            @Override
            public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
                Insets insets = outsideBorder.getBorderInsets(c);
                Font font = c.getFont();
                FontMetrics metrics = c.getFontMetrics(font);
                int by = (c.getHeight() / 2) + (metrics.getAscent() / 2) - insets.top;
                int bw = Math.max(2, insets.left); // border width
                int iw = metrics.stringWidth("=="); // icon width
                int bx = x + width - (Math.round(iw * 1.5f) + (bw * 2)) + 2;
                g.translate(bx, by);
                g.setColor(Color.RED);
                g.setFont(c.getFont().deriveFont(Font.BOLD, font.getSize()));
                g.drawString("==", x + (iw / 2), y);
            }

            @Override
            public boolean isBorderOpaque() {
                return true;
            }

            @Override
            public Insets getBorderInsets(Component c, Insets insets) {
                insets.right = 15;
                return insets;
            }
        }));
        this.add(field);
        this.pack();
        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        this.setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Borders().setVisible(true);
        });
    }

}