2012-11-02 49 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测量,所有问题都没有了,理由也可以根据需要进行调整。