我需要使用Graphics#drawString
绘制文字我正在绘制宽度和高度都变化的JPanel
(通过拖动)。
我正在寻找一种生成边界的解决方案,这样我就可以自动扭曲线条并相应调整文本,而不会溢出。
我想我可以通过使用fontMetrics获取像素的长度来自己进行硬编码,但是,我希望有一个自动执行此操作的组件(drawString
也不支持'\n'
)。
在文档以及this其他答案中,我发现了这一点:
Graphics2D g = ...;
Point2D loc = ...;
Font font = Font.getFont("Helvetica-bold-italic");
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout("This is a string", font, frc);
layout.draw(g, (float)loc.getX(), (float)loc.getY());
Rectangle2D bounds = layout.getBounds();
bounds.setRect(bounds.getX()+loc.getX(),
bounds.getY()+loc.getY(),
bounds.getWidth(),
bounds.getHeight());
g.draw(bounds);
它绘制字符串和边界,但它们没有效果,所以这里没有运气。
我可以使用的任何课程吗?
答案 0 :(得分:7)
我可以使用的任何课程吗?
另一种选择是使用LineBreakMeasurer:
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
import java.util.Objects;
import javax.swing.*;
import javax.swing.border.Border;
public final class LineBreakMeasurerTest {
private static final String TEXT = "1234567890 ABCDEFG HIJKLMN OPQRSTU VWXYZ";
private final JLabel lbl1 = new JLabel(TEXT);
private final JTextArea lbl2 = new JTextArea(TEXT);
private final JLabel lbl3 = new WrappingLabel(TEXT);
public JComponent makeUI() {
Border b = BorderFactory.createLineBorder(Color.GREEN, 5);
lbl1.setBorder(
BorderFactory.createTitledBorder(b, "JLabel"));
lbl2.setBorder(
BorderFactory.createTitledBorder(b, "JTextArea"));
lbl3.setBorder(
BorderFactory.createTitledBorder(b, "LineBreakMeasurer"));
lbl2.setFont(lbl1.getFont());
lbl2.setEditable(false);
lbl2.setLineWrap(true);
lbl2.setWrapStyleWord(true);
lbl2.setBackground(lbl1.getBackground());
JPanel p = new JPanel(new GridLayout(3, 1));
p.add(lbl1);
p.add(lbl2);
p.add(lbl3);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
UIManager.put("swing.boldMetal", Boolean.FALSE);
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new LineBreakMeasurerTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class WrappingLabel extends JLabel {
//TEST: private AffineTransform at = AffineTransform.getScaleInstance(.8, 1d);
protected WrappingLabel(String text) {
super(text);
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(getForeground());
Insets i = getInsets();
float x = i.left;
float y = i.top;
int w = getWidth() - i.left - i.right;
AttributedString as = new AttributedString(getText());
//TEST: as.addAttribute(TextAttribute.FONT, g2.getFont());
//TEST: as.addAttribute(TextAttribute.TRANSFORM, at);
AttributedCharacterIterator aci = as.getIterator();
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
while (lbm.getPosition() < aci.getEndIndex()) {
TextLayout tl = lbm.nextLayout(w);
tl.draw(g2, x, y + tl.getAscent());
y += tl.getDescent() + tl.getLeading() + tl.getAscent();
}
g2.dispose();
}
}
答案 1 :(得分:2)
最简单的解决方案:使用JTextArea。
你可以通过将背景设置为null来使其看起来像JTextArea,使其不可聚焦,并且如果你调用setLineWrap(true)
和{{1 }} 在上面。要让它填充JPanel,给面板一个BorderLayout,并添加JTextArea BorderLayout.CENTER。如果需要,您甚至可以设置保证金。