2016-12-13 9 views
2

我需要繪製的文本與Graphics#drawStringdrawString之秋千:文本邊界和換行

我借鑑了JPanel,無論在寬度和高度(通過拖動)發生變化的頂部。

我正在尋找一個解決方案來生成邊界,以便我可以自動扭曲線條並相應地調整文本,而不會溢出。

我想我可以通過使用fontMetrics獲取像素長度來自己硬編碼,但是我寧願有一個自動執行此操作的組件(drawString也不支持'\n')。這裏

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

這確實提請串和邊界,但他們沒有任何影響,所以沒有運氣:

在文檔以及其他this答案,我發現這一點。

我可以使用的任何課程?

回答

6

我可以使用的任何課程?

另一種選擇是使用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(); 
    } 
} 
2

最簡單的解決方案:使用JTextArea。

您可以通過將背景設置爲null而使其看起來不像JTextArea,因爲它無法聚焦,如果您對其調用setLineWrap(true)setWrapStyleWord(true),它會自動包裝單詞。爲了讓它填充JPanel,給面板一個BorderLayout,並添加JTextArea BorderLayout.CENTER。如果需要,您甚至可以設置保證金。

+0

謝謝回答。我爲此付出了努力,但沒有其他辦法嗎? 這樣做會有很多麻煩,因爲它不是一個統一的文本。這是很多小字符串,沒有被分配,具有不同的格式,顏色,規格。 這裏有一個很簡單的模式,其中有一些:http://imgur.com/4zKTppM 紅色的表格是虛構的,僅用於顯示對齊。 字符串獨立更新,這個面板非常小,有相當多的人.. –