【问题标题】:How to do image rendering using bufferedimage in a jframe?如何在 jframe 中使用 bufferedimage 进行图像渲染?
【发布时间】:2021-03-13 21:37:09
【问题描述】:

我正在尝试渲染一组复杂的对象,而不是尝试单独渲染每个对象,我认为将它们渲染为 BufferedImage 会更快。我能弄清楚如何做到这一点的唯一方法是将 BufferedImage 转换为 ImageIcon,并将其设置为 JLabel,然后将 JLabel 添加到 JFrame。为了更新图像,我删除了 JLabel,使用新的 BufferedImage 对其进行设置,然后将其重新添加到 JFrame。这会使屏幕快速闪烁,因为您可以在每次渲染之间看到一个空帧。如果我不删除标签,程序运行非常缓慢。我该如何解决?我应该使用 JLabels 还是有更好的方法?

    public static void createWindow() {
        frame = new JFrame("PlanetSim");
        
        frame.setPreferredSize(new Dimension(WINDOW_X, WINDOW_Y));
        frame.setMaximumSize(new Dimension(WINDOW_X, WINDOW_Y));
        frame.setMinimumSize(new Dimension(WINDOW_X, WINDOW_Y));

        foregroundLabel = new JLabel(new ImageIcon(foreground));
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(foregroundLabel);
        frame.pack();
        
        frame.setVisible(true);
    }

    public static void setForeground() {
        frame.getContentPane().remove(foregroundLabel);
        foregroundLabel = new JLabel(new ImageIcon(foreground));
        frame.getContentPane().add(foregroundLabel);
        frame.pack();
    }

我怀疑这个问题与循环本身有关,但我还是把它包括在内以防万一。

    public void run() {
        long lastTime = System.nanoTime(), now; //keeps track of time on computer in nanoseconds
        double amountOfTicks = 60.0; //number of ticks per rendering
        double delta = 0; //time step 
        long timer = System.currentTimeMillis(); //timer to display FPS every 1000 ms
        int frames = 0;

        while (running) {
            now = System.nanoTime();
            delta += (now - lastTime) * amountOfTicks / 1000000000;
            lastTime = now;
            while(delta >= 1) {
                tick();
                delta--;
            }
            if (running)
                render();
            frames++;

            if (System.currentTimeMillis() - timer > 1000) {
                timer += 1000;
                System.out.println("FPS: " + frames);
                frames = 0;
            }
        }   
    }

    public void render() {
        populateWindow();
        Window.setForeground();
    }

【问题讨论】:

标签: java swing rendering jlabel bufferedimage


【解决方案1】:
    frame.getContentPane().remove(foregroundLabel);
    foregroundLabel = new JLabel(new ImageIcon(foreground));
    frame.getContentPane().add(foregroundLabel);
    frame.pack();

我建议不需要删除/添加标签或打包框架,因为我会假设图标每次都是相同的大小。

您需要做的就是替换标签的图标。

    //frame.getContentPane().remove(foregroundLabel);
    foregroundLabel.setIcon( new ImageIcon(foreground) );
    //frame.getContentPane().add(foregroundLabel);
    //frame.pack();

我正在尝试渲染一组复杂的对象,而不是尝试单独渲染每个对象,我认为将它们渲染为 BufferedImage 会更快

否则,只需在您的 paintComponent() 方法中进行渲染。 Swing 默认情况下是双缓冲的,因此它基本上消除了创建 BufferedImage 的需要。

请参阅:get width and height of JPanel outside of the class,了解自定义绘画的示例。只需将球数从 5 更新为 100 以使其更复杂。

【讨论】:

  • 谢谢!我做了你建议的改变,它已经停止闪烁。我看到有人推荐使用 BufferStrategy 而不是将所有内容发送到缓冲图像并将其设置为图标。一个比另一个快还是相当?
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 2019-06-08
  • 2014-01-18
  • 2014-04-17
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
相关资源
最近更新 更多