0

我有一些 Graphics2D 区域,我在其中绘制几何图元。它可以使用 g2.scale(x, y) 轻松缩放。现在我想在我的可扩展区域中绘制一些文本并直接在其中编辑文本。它也有效,但不幸的是有一个问题,可以说明。这是它以 100% 的比例查看监视器的方式: 在此处输入图像描述

这就是 300% 发生的情况:

在此处输入图像描述

字母“A”的位置几乎可以,但字母B的位置左右跳跃。我想 JEditorPane 只是采用最近的字体来呈现缩放字体。不同字体的空间大小可能会略有不同(以像素为单位)。这在字符串的开头并没有真正产生问题,但在结尾处错误会累积。

我怎样才能实现 JEditorPane 在任何 g2.scale() 的完全相同的位置呈现字体?(例如,OpenOffice 工作正常,同样的问题)。

升级版: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);
    }
}
4

2 回答 2

2

看到有http://java-sl.com/articles.html文章关于 JEditorPane 缩放。“使用自定义 GlyphPainter 和分数测量支持进行缩放”一文解释了字体缩放和测量问题。您可以使用基于 TextLayout 或基于 GlyphVector 的绘画来修复分数 fnt 测量。

于 2012-11-02T13:50:19.497 回答
1

我和同一个战斗了一段时间。当您尝试右对齐文本并使用较小的字体(因此行上有很多字符)时,问题会更大。缩放只是乘以错误并使其易于可见。

使用上面提到的“使用自定义 GlyphPainter 和分数测量支持进行缩放”文章和代码将有助于从 int 切换到 float 消除舍入误差。它几乎可以正常工作,但不完全是,即那里正在发生其他事情。

在 ScaledGlyphPainter.getTabbedTextWidth 我替换了实际测量

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 测量,所有问题都消失了,并且可以根据需要进行调整。

于 2013-03-21T22:51:22.110 回答