我正在尝试使用大纲效果创建自定义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);
文字很好,但这是不可接受的,因为标签必须在更复杂的布局中使用多次,我不能每次基于标签位置进行平移,我需要更通用的解决方案。
有人能帮助我吗?
答案 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,从类外部设置首选大小就足够了。