繁体   English   中英

JavapaintComponent从数组绘制数百万个正方形的最有效方法

[英]Java- paintComponent most efficient way of drawing millions of squares from an array

我已经基于一些示例编写了一个程序来模拟Conway的生活游戏。 游戏中的每个单元都是活着的或死亡的,它们存储在整数int[][]数组中,该数组始终至少为1000 * 1000,这意味着有数百万个单元。

遍历数组以找到适用所有不同规则的方法很好,并且CPU占用不是特别大。 但是,用于在JFrame上绘制这些矩形的方法可能会导致Xeon E3 1246 V3(I7 4770)上的CPU使用率超过90%。 在2000 ^ 2的数组大小上,它可能会导致Windows 10完全硬锁定。

@Override
    protected void paintComponent(Graphics g) {
        liveCells = 0;
        super.paintComponent(g);
        Color gColor = g.getColor();
        if(!backgroundWork || isPaused) {
            for (int row = 0; row < grid.length; row++) {
                for (int column = 0; column < grid[row].length; column++) {
                    //Checking if the cell is alive.
                    if (grid[row][column] == 1 ) {
                        liveCells++;
                        g.setColor(Color.red);
                        g.fillRect(column * UIScale, row * UIScale, UIScale, UIScale);

                    }
                }
            }
        }

        g.setColor(gColor);
        if (isPaused) { 
            g.drawString("The game is paused", 0, 30);
            g.drawString("Generation: " + generationCounter, 0, 10);
            g.drawString("Living cells: " + liveCells, 150, 10);
        } else { //If the game is running
            g.drawString("Generation: " + generationCounter++, 0, 10);
            g.drawString("Living cells: " + liveCells, 100, 10);
        }
        g.setColor(gColor);
        try {
            /* Sleep for some microseconds. */
            TimeUnit.MICROSECONDS.sleep(sleepTimer);
        } catch (InterruptedException ex) {
            System.err.println("An InterruptedException was caught: " + ex.getMessage());
        }
    }

我可以很清楚地看到单元格的绘制是问题所在,为了使程序运行得更快,我已经添加了一种更改变量backgroundWork的方法,该方法禁止更新矩形网格。 启用或禁用此选项将导致任务管理器CPU利用率差异高达80%。

使用当前的绘制网格的方法,我看不到使网格更快的方法,因为所有单元格彼此独立,并且通常不会有超过3个彼此相邻的红色,因此没有理由实施一次同时绘制多个图形的方法。

谁能建议一种加快当前过程的方法,或者另一种绘制正方形的方法。 谢谢你的帮助。

这种方法是由Hovercraft Full Of Eels(顺便说一句好名字)建议的,比我以前使用的方法要快得多,

@Override
protected void paintComponent(Graphics g) {
    liveCells = 0;

    BufferedImage BI = new BufferedImage(UIDimensions, UIDimensions, BufferedImage.TYPE_INT_RGB);

    super.paintComponent(g);
    Color gColor = g.getColor();
    if(!backgroundWork || isPaused) {
        for (int row = 0; row < grid.length; row++) {
            for (int column = 0; column < grid[row].length; column++) {
                //Checking if the cell is alive.
                if (grid[row][column] == 1 ) {
                    liveCells++;
                    if(UIScale != 1) {
                        //TODO- Draw squares larger than one pixel
                    } else {
                        BI.setRGB(column, row, 16711680);
                    } 

                    //The old code is commented out below

                    //g.setColor(Color.red);
                    //Drawing the colour in a 4x4 pixel square. With a window of 1000x1000, there are 250x250 organisms, hence the /4 everywhere
                    //g.fillRect(column * UIScale, row * UIScale, UIScale, UIScale);
                    //The way that this works is that it draws rectangles at the coordinates of the grid.
                    //The graphics on the screen aren't a grid themselves, they are just lots of squares
                } else {
                    BI.setRGB(column, row, 16777215);
                }
            }
        }
        g.drawImage(BI, 0, 0, null);
    }

    g.setColor(gColor);

    if (isPaused) { //If the game is paused (isPaused is true)
        g.drawString("The game is paused", 0, 30);
        g.drawString("Generation: " + generationCounter, 0, 10);
        g.drawString("Living cells: " + liveCells, 150, 10);
    } else { //If the game is running
        g.drawString("Generation: " + generationCounter++, 0, 10);
        g.drawString("Living cells: " + liveCells, 100, 10);
    }
    g.setColor(gColor);
    try {
        /* Sleep for some seconds. */
        TimeUnit.MICROSECONDS.sleep(sleepTimer);
    } catch (InterruptedException ex) {
        System.err.println("An InterruptedException was caught: " + ex.getMessage());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM