JLabel的文本超出范围

时间:2017-02-04 23:24:55

标签: java swing awt jlabel

我正在尝试使用大纲效果创建自定义JLabel,这是我的代码:

package test;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;

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

public class OutlineLabel extends JLabel {

    private Color outlineColor = Color.BLACK;
    private Color fillColor = Color.WHITE;


    public OutlineLabel() {
        super();

    }
    public void setThin(int thin){
        //this.thin=thin;
    }
    public OutlineLabel(String text,Color inline,Color outline) {
        super(text);
        outlineColor=outline;
        fillColor=inline;
    }

    @Override
    public void paintComponent(Graphics g) {
        String text = getText();

        BasicStroke outlineStroke = new BasicStroke(1.5f);

        if (g instanceof Graphics2D) {
            Graphics2D g2 = (Graphics2D) g;

            // remember original settings
            Color originalColor = g2.getColor();
            Stroke originalStroke = g2.getStroke();
            RenderingHints originalHints = g2.getRenderingHints();


            // create a glyph vector from your text
            GlyphVector glyphVector=g.getFont().layoutGlyphVector(g2.getFontRenderContext(),text.toCharArray(),0,text.length(),Font.LAYOUT_LEFT_TO_RIGHT);

            // get the shape object
            Shape textShape = glyphVector.getOutline();

            // activate effects
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                    RenderingHints.VALUE_RENDER_QUALITY);

           //g.translate(getX(), getY()+160);
            g2.setColor(outlineColor);
            g2.setStroke(outlineStroke);
            g2.draw(textShape); // draw outline

            g2.setColor(fillColor);
            g2.fill(textShape); // fill the shape

            // reset to original settings after painting
            g2.setColor(originalColor);
            g2.setStroke(originalStroke);
            g2.setRenderingHints(originalHints);
        }
    }

    public static void main(String[] args) {
        JFrame w = new JFrame();
        w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Font myFont = new Font("Arial", Font.BOLD,146);
        OutlineLabel label = new OutlineLabel("TEST",Color.red,Color.yellow);
        label.setFont(myFont);
        JPanel p=new JPanel();
        p.add(label);
        w.setContentPane(p);
        w.pack();
        w.setVisible(true);
    }
}

问题是文本是在组件范围之外绘制的......我想了解为什么以及如何解决这个问题,你可以验证从以下位置删除注释:

g.translate(getX(), getY()+160);

文字很好,但这是不可接受的,因为标签必须在更复杂的布局中使用多次,我不能每次基于标签位置进行平移,我需要更通用的解决方案。

有人能帮助我吗?

1 个答案:

答案 0 :(得分:0)

好的,我找到了解决方法。 如果其他人有同样的问题: 我不知道为什么,但是打电话:

Shape textShape = glyphVector.getOutline();

textShape自动转换为形状本身的高度。 所以它超出了界限。如果要将其放回组件的中心(垂直对齐),则需要AffineTransform。在我之前发布的示例中,足以替换此行:

g.translate(getX(), getY()+160);

用这些:

int heightComponent=getHeight();
int heightShape=(int)textShape.getBounds().getHeight();
final AffineTransform transform = AffineTransform.getTranslateInstance(
                  0,heightShape+((int)heightComponent/2-heightShape/2));
textShape=transform.createTransformedShape(textShape);

N.B。我的第一篇文章的评论是完全错误的。您可以扩展Label,完全没问题......而且您不需要覆盖getPreferredSize,从类外部设置首选大小就足够了。