【问题标题】:Drawing Pixels with mouse to BufferedImage - imrpoving performance用鼠标将像素绘制到 BufferedImage - 提高性能
【发布时间】:2015-05-04 20:54:17
【问题描述】:

我从 Processing 编程切换到 Java,现在,我正在尝试将一些技术转换为纯 Java 编程语言。 似乎我的代码有时会滞后,而且它也比我的处理草图慢。我是不是搞错了什么?我怎样才能改进我的代码?这种计算是否也适用于 gpu 计算,也许在 lwjgl 中?

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.Canvas;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;

public class Main extends Canvas implements Runnable {

    public static final int WIDTH = 1280;
    public static final int HEIGHT = 800;

    private int xstart;
    private int ystart;
    private int xend;
    private int yend;

    private int xPos;
    private int yPos;

    private Thread thread;
    private boolean isRunning = false;
    private BufferedImage img;
    private int[] pixels;

    private Random r;

    public Main() {
        img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

        pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
        r = new Random();

        xPos = WIDTH / 2;
        yPos = HEIGHT / 2;

        xstart = xPos - 200;
        ystart = yPos - 200;
        xend = xPos + 200;
        yend = yPos + 200;
    }

    @Override
    public void run() {
        while (isRunning) {
            render();
        }
    }

    private void start() {
        if (isRunning)
            return;
        isRunning = true;
        thread = new Thread(this);
        thread.start();
    }

    private void stop() {
        if (!isRunning)
            return;
        isRunning = false;
        try {
            thread.join();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }

    private void render() {
        addMouseMotionListener(new MouseMotionListener() {
            public void mouseDragged(MouseEvent e) {
                xPos = e.getX();
                yPos = e.getY();
            }

            public void mouseMoved(MouseEvent e) {
            }
        });

        addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e) {
                xPos = e.getX();
                yPos = e.getY();

            }

            public void mousePressed(MouseEvent e) {
                xPos = e.getX();
                yPos = e.getY();

            }

            public void mouseReleased(MouseEvent e) {
                xPos = e.getX();
                yPos = e.getY();
            }

            public void mouseEntered(MouseEvent e) {
            }

            public void mouseExited(MouseEvent e) {
            }
        });
        xstart = xPos - 50;
        ystart = yPos - 50;
        xend = xPos + 50;
        yend = yPos + 50;

        if (xstart < 0)
            xstart = 0;
        if (xstart > WIDTH)
            xstart = WIDTH;
        if (ystart < 0)
            ystart = 0;
        if (ystart > HEIGHT)
            ystart = HEIGHT;
        if (xend < 0)
            xend = 0;
        if (xend > WIDTH)
            xend = WIDTH;
        if (yend < 0)
            yend = 0;
        if (yend > HEIGHT)
            yend = HEIGHT;

        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(3);
            return;
        }

        for (int i = 0; i < WIDTH * HEIGHT; i++) {
            pixels[i] *= 0.99;
            if (pixels[i] <= 0)
                pixels[i] = 0;
        }

        for (int y = ystart; y < yend; y++) {
            for (int x = xstart; x < xend; x++) {
                int i = x + y * WIDTH;
                pixels[i] = r.nextInt(0xffffff);
            }
        }

        Graphics g = bs.getDrawGraphics();
        g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
        g.dispose();
        bs.show();
    }

    public static void main(String[] args) {
        Main main = new Main();
        JFrame frame = new JFrame();
        frame.add(main);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);
        main.start();
    }
}

【问题讨论】:

  • 1) 您不需要为每次渲染迭代添加新的侦听器 - 添加一次 2) 我建议避免混合 awt 和 Swing - 使用 JComponent 并覆盖它的 paintComponent 方法渲染 3) 对 EDT 的非线程安全调用应通过SwingUtilities 分派。
  • “对 EDT 的非线程安全调用”是什么意思?谢谢你的小费,我马上试试
  • 顺便问一下:不是来自 AWT 的 BufferedImage 吗?所以这也意味着我会将 awt 与 swing 混合使用
  • 我应该指定 Swing 和 AWT Components,或者更具体地说是 heavyweight and lightweight Components

标签: java drawing mouse bufferedimage pixels


【解决方案1】:

每次调用 render 时,您都会添加新的 MouseListeners,这意味着,每次出现 MouseEvent 时,他们都必须通知并且不断增加的侦听器列表,所有这些似乎都在做同样的事情......

相反,在构造函数中设置你的监听器

我还建议摆脱“渲染线程”,仅在您希望更新屏幕时调用您的渲染方法(使用被动绘画而不是主动渲染)

【讨论】:

  • 我想构建一个类似游戏的 CA,它在鼠标位置周围呈现一个受限区域。如果没有渲染循环,这也可以吗?感谢您的建议,立即尝试!
  • 您仍然可以使用“渲染”循环,只是不要在其中重新附加更多 MouseListeners
猜你喜欢
  • 2015-07-22
  • 2020-02-17
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
  • 2011-07-01
  • 2011-05-14
  • 2015-03-12
相关资源
最近更新 更多