2012-10-29 76 views
2

我不知道我做錯了......的Java Swing的顯示drawString之回聲

我想作一個JComponent顯示自定義字體,自定義顏色(包括漸變背景),等等。它的工作原理串很好,但我在組件的左上角看到了字符串的底部。下面的代碼簡化了很多組件,允許集中在這個問題上...

InfoPanel.java

import java.awt.*; 
import java.awt.font.*; 
import java.awt.geom.Rectangle2D; 

import javax.swing.*; 

/** 
* Panel showing information. 
*/ 
@SuppressWarnings("serial") 
class InfoPanel extends JComponent 
{ 
    private String m_information; 
    private Font m_font; 
    private Color m_colorForeground; 
    private Color m_colorBackground; 

    protected float heightFactor; 
    protected int m_alignment = SwingConstants.CENTER; 

    InfoPanel(String info, Font font, Color colorFore, Color colorBackground) 
    { 
    m_information = info; 
    m_font = font; 
    m_colorForeground = colorFore; 

    if (colorFore == null) 
    { 
     m_colorForeground = Color.BLACK; 
    } 
    if (colorBackground == null) 
    { 
     m_colorBackground = Color.GRAY; 
    } 
    else 
    { 
     m_colorBackground = colorBackground; 
    } 
    setOpaque(true); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
    final Graphics2D g2d = (Graphics2D) g.create(); 
    g2d.setFont(m_font); 

    g2d.setColor(m_colorBackground); 
    Dimension d = getSize(); 
    g2d.fillRect(0, 0, d.width, d.height); 
    g2d.setColor(m_colorForeground); 

    // Get the text bounds 
    FontRenderContext fontContext = g2d.getFontRenderContext(); 
    TextLayout layout = new TextLayout(m_information, m_font, fontContext); 
    layout.draw(g2d, 0, 0); 
    Rectangle2D bounds = layout.getBounds(); 

    int posX = 10; 
    int width = (int) bounds.getWidth(); 
    int height = (int) bounds.getHeight(); 
    if (m_alignment == SwingConstants.CENTER) 
    { 
     posX = (d.width - width)/2; 
    } 
    else if (m_alignment == SwingConstants.RIGHT) 
    { 
     posX = d.width - width - posX; 
    } 
    // Center vertically 
    FontMetrics fm = g2d.getFontMetrics(); 
    int posY = d.height/2 + height/2 - fm.getDescent(); 

    g2d.drawString(m_information, posX, posY); 
    // Only drawString shows this problem! 
    g2d.drawLine(posX, posY + 5, posX + width, posY + 5); 

    g2d.dispose(); 
    } 
} 

TestInfoPanel.java

import java.awt.*; 

import javax.swing.*; 

public class TestInfoPanel 
{ 
    private JPanel m_panel; 

    TestInfoPanel() 
    { 
    } 

    private JScrollPane getContent() 
    { 
    m_panel = new JPanel(new GridLayout(0, 1)); 
    m_panel.add(new InfoPanel("A Title [email protected],;!§", 
     new Font("Arial", Font.PLAIN, 24), 
     Color.RED, Color.LIGHT_GRAY)); 
    m_panel.add(new InfoPanel("A Sub-Title [email protected],;!§", 
     new Font("Tahoma", Font.PLAIN, 18), 
     Color.BLUE, Color.YELLOW)); 
    m_panel.add(new JPanel()); 
    return new JScrollPane(m_panel); 
    } 

    public static void main(String[] args) 
    { 
    final TestInfoPanel tm = new TestInfoPanel(); 
    SwingUtilities.invokeLater(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setTitle(tm.getClass().getName()); 
     f.setContentPane(tm.getContent()); 
     f.setSize(800, 400); 
     f.setLocation(200, 200); 
     f.setVisible(true); 
     } 
    }); 
    } 
} 

這裏是我的請參閱: Graphics Bug: echo of text 在Windows 7上測試,見於Java 5,6,7。

+0

覆蓋PREFERREDSIZE爲JComponent的 – mKorbel

回答

3

看起來好像layout.draw在左上角繪製文本,然後使用g2d.drawString再次繪製文本。您可以刪除g2d.drawString,並將其正確位置直接傳遞給layout.draw

layout.draw(g2d, posX, posY); 

(或刪除layout,並且只使用g2d.drawString,似乎工作爲好。)

+0

它的工作原理...(我只是刪除了layout.draw())。我找到了獲取文本邊界的方法,包括這個draw(),我認爲有必要觸發計算,並假定它是一個空白操作,但顯然不是和不是(不必要也不是空白!)。發現得好!謝謝。 – PhiLho