简体   繁体   中英

Text of JLabel out of bounds

I'm trying to create a custom JLabel with the outline effect this is my code:

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);
    }
}

The problem is that the text is drawn outside the bounds of the components... I would like to understand why and how to fix this, you can verify that remove the comment from :

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

The text is well drawn, but this is no acceptable because the label has to be used in a more complex layout and multiple times, I cannot translate every time the coordinate basing on the label position, I need a more generic solution.

Can somebody help me?

Ok I have found a solution for that. If somebody else have the same problem: I don't know why but calling:

Shape textShape = glyphVector.getOutline();

the textShape is automatic translated up of the height of the shape itself. So it goes out of bounds. If you want to put it back in the center of the component (Vertical Alignment) you need a AffineTransform. In the example I have posted before is enough to replace this line :

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

with these:

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);

NB The comments on my first post are completely wrong. You can extends Label, no problem at all... and you don't need to override the getPreferredSize , setting the preferred size from outside the class is enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM