【问题标题】:Java2D drawString very slow?Java2D drawString 很慢?
【发布时间】:2020-01-29 14:07:47
【问题描述】:

我正在尝试使用 Java Swing/AWT 2D 图形在窗口中显示一些非常基本的信息。此时,我只是在画一些字符串,虽然这个任务看起来并不难,但它运行起来非常慢。

在什么都不画的情况下,我可以以 100 FPS 左右的速度重新绘制。使用 1 个字符串,大约 30 FPS。有 20 个字符串,大约 3 FPS。

小例子:

import javax.swing.*;
import java.awt.*;

public class Example {
    public static void main(String[] args) {
        JFrame frame = buildFrame();
        JPanel pane = new JPanel() {
            int counter = 0;

            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D)g;
                g2.setColor(Color.black);
                g2.drawString(Integer.toString(counter++), 20, 20);
                g2.drawString("HALLO", 50, 50);
                g2.drawString("HALLO", 50, 60);
                g2.drawString("HALLO", 50, 70);
                g2.drawString("HALLO", 50, 80);
                g2.drawString("HALLO", 50, 90);
                g2.drawString("HALLO", 50, 100);
                g2.drawString("HALLO", 50, 110);
                g2.drawString("HALLO", 50, 120);
                g2.drawString("HALLO", 50, 130);
                g2.drawString("HALLO", 50, 140);
                g2.drawString("HALLO", 50, 150);
                g2.drawString("HALLO", 50, 160);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 160);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 170);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 180);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 190);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 100);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 110);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 120);
                g2.drawString("DIES IST NUR EINT EST FÜR EINEN LANGENSTRING", 200, 130);
                g2.dispose();
            }
        };
        frame.add(pane);

        while (true) {
            pane.repaint();
            frame.setVisible(true);
        }
    }

    private static JFrame buildFrame() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(480, 272);
        frame.setVisible(true);
        return frame;
    }
}

我在树莓派 3b+ 上运行,这不是一台非常快的机器,但应该能够显示一些字符串。使用System.nanoTime 对函数计时表明主循环和paintComponent 函数都低于1ms,这让我更加困惑。

我是否从根本上错过了什么?

【问题讨论】:

  • “这个任务似乎没有那么难”——好吧,渲染文本比你想象的要难,需要进行大量计算才能确定哪些像素应该着色,哪些不应该着色。除此之外,我可以想象硬件加速未启用甚至不可用 - 如果这是真的,那么一切都必须在非常慢的软件中完成。
  • 既然你想展示“非常基本的信息”,为什么不简单地使用组件呢?喜欢JLabel 左右..
  • 代码中另一个可能的问题是g2.dispose();。来自dispose() 上的 JavaDoc:“...为了提高效率,程序员应该在使用完 Graphics 对象后调用 dispose,前提是它是直接从组件或另一个 Graphics 对象创建的。” - 你没有创建g2,所以你不应该自己处理它。
  • 您不应该丢弃Graphics,因为 JPanel 将继续使用它。
  • “实际上使用 JLabels 确实快很多” 提示:添加@GeorgeZ。 (或@ 很重要的人)通知新评论的人。

标签: java swing graphics awt java-2d


【解决方案1】:

先把你的字符串画成一个 BufferedImage 怎么样:

BufferedImage bi = new BufferedImage(pane.getSize().width, pane.getSize().height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2D = bi.createGraphics();
g2D.drawString("HALLO", 50, 50);
...
g2D.dispose();

缓存它,然后在您的paintComponent() 中绘制图像

g2D.drawImage(bi, 0, 0, this);

【讨论】:

    猜你喜欢
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2011-03-08
    • 2013-02-23
    • 2015-12-24
    • 2020-10-23
    相关资源
    最近更新 更多