2012-11-02 46 views
0

我有一個Graphics2D區域,在那裏繪製幾何圖元。它可以通過g2.scale(x,y)輕鬆縮放。現在我想在可縮放區域繪製一些文字,並將文字編輯到其中。它也可以工作,但不幸的是有一個問題可以說明。這是它的外觀,在顯示器100%: enter image description hereJEditorPane和字體比例尺

這就是在300%會發生什麼:

enter image description here

萊特的位置「A」幾乎是OK,但位置字母B左右跳躍。 我想JEditorPane只是採用最近的字體來渲染縮放字體。不同字體的空間可能會以像素略有不同。這在字符串的開始處並不真正產生問題,但最終會累積錯誤。

我該如何實現JEditorPane呈現字體在任何g2.scale()完全相同的位置? (例如,OpenOffice可以正確處理相同的問題)。

UPD:SSCCE

class Canvas extends JPanel { 
    @Override 
    public void paint(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     g.translate(p.x, p.y); 
     g2.scale(scale, scale); 
     g2.setColor(Color.GRAY); 
     g2.fill(g2.getClip()); 

     JEditorPane pane = new JEditorPane(); 
     pane.setFont(pane.getFont().deriveFont(22f)); 
     pane.setText("A                        B"); 
     pane.setBounds(new Rectangle(100, 100, 700, 30)); 
     g2.translate(100, 100); 
     pane.paint(g2); 
     g2.translate(-100, -100); 

     g2.setColor(Color.BLACK); 
     g2.draw(new Rectangle(100, 100, 700, 30)); 


     g2.scale(1/scale, 1/scale); 
     g.translate(-p.x, -p.y); 
     g2.setColor(Color.GREEN); 
     g2.setFont(g2.getFont().deriveFont(33f)); 
     g2.drawString("Scale (mouse wheel): " + new DecimalFormat("#.##").format(scale * 100) + "%", 2, 768-66); 
     g2.drawString("(Drag mouse to move)", 2, 768-33); 
    } 


// +++++++++++++++++++++++++++ GUI +++++++++++++++++++++++++++++++++++++ 

    public Canvas() { 
     addMouseWheelListener(new MouseWheelListener() { 
      @Override 
      public void mouseWheelMoved(MouseWheelEvent e) { 
       scale += e.getWheelRotation() * 1.0/10; 
       repaint(); 
      } 
     }); 

     addMouseMotionListener(new MouseMotionAdapter() { 
      @Override 
      public void mouseDragged(MouseEvent e) { 
       p.x = e.getPoint().x - startDrag.x; 
       p.y = e.getPoint().y - startDrag.y; 
       repaint(); 
      } 
     }); 

     addMouseListener(new MouseAdapter() { 
      @Override 
      public void mousePressed(MouseEvent e) { 
       startDrag = e.getPoint(); 
       startDrag.x -= p.x; 
       startDrag.y -= p.y; 
      } 
     }); 
    } 

    public static double scale = 1.0; 
    public static Point p = new Point(); 
    public static Point startDrag = new Point(); 
} 

public class Main { 
    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     frame.add(new Canvas()); 

     frame.setSize(1024, 768); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
+0

請修改您的問題以包含展示您描述的問題的[sscce](http://sscce.org/)。 – trashgod

+0

另請參閱此「TextLayout」[示例](http://stackoverflow.com/a/4287269/230513)。 – trashgod

+0

更新:sscce添加了 – AvrDragon

回答

2

見緊靠JEditorPane的比例有http://java-sl.com/articles.html文章。 「定製GlyphPainter和分數度量支持的縮放」文章解釋了字體縮放和測量問題。您可以使用基於TextLayout或基於GlyphVector的繪畫來修復小數fnt測量。

+0

> GlyphPainter1(遺憾的是它不公開) 是GlyphPainter1還沒公開? – AvrDragon

+0

您可以編寫自己的GlyphPainter或使用第二篇文章中描述的GlyphPainter。 – StanislavL

1

我一直在與同一個人搏鬥一段時間。當您嘗試右對齊文本並使用小字號(因此行中有很多字符)時,問題會更大。縮放只是使錯誤變得更加容易看到。

使用上面提到的「自定義GlyphPainter和分數度量支持的縮放」文章和代碼將有助於從int到float的切換擺脫舍入誤差。它的工作幾乎沒有問題,但不完全正確,即在那裏發生了其他事情。

在ScaledGlyphPainter.getTabbedTextWidth我更換了實際mensurment

nextX += metrics.getStringBounds(txtStr, n - charCount, n, painterGr).getWidth(); 

隨着

FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true); 
TextLayout layout = new TextLayout (text, metrics.getFont(), frc); 
nextX += layout.getBounds().getWidth(); 

顯然,這兩種測量將在相同的文本返回不同的結果!!!!如果測量發生在另一個方向上,則會出現繪圖錯誤。一旦我改變了上面的代碼來使用TextLayout測量,所有問題都沒有了,理由也可以根據需要進行調整。