绘制程序未使用并行数组正确存储大小和颜色

Posted

技术标签:

【中文标题】绘制程序未使用并行数组正确存储大小和颜色【英文标题】:Paint program not using parallel arrays to store size and color properly 【发布时间】:2014-11-03 04:26:41 【问题描述】:

这是一个简单的绘画风格程序,基于使用数组和数组列表来保存使用 JFrame、paintComponent 和各种鼠标侦听器在屏幕上绘制的不同点的坐标、大小和颜色。

我最近修复了一个问题,它会吐出一个 ArrayOutOfBounds 错误并指向第 34 行,其中颜色数组超过了 10000 的限制。但是我需要运行程序并且每个点的大小和颜色相互平行,所以每次程序重新绘制点时,每个点都会保留自己的大小和颜色变量。感谢您的意见!

    import java.util.ArrayList;
    import javax.swing.JPanel;
    import java.awt.*;
    import java.awt.event.*;

    public class Proj1Panel extends JPanel
        public int SIZE = 5, c = 0, s = 0;

        private ArrayList<Point> pointList;
        public int[] sizes;
        public Color[] colors;

        public Proj1Panel()
            pointList = new ArrayList<Point>();
            sizes = new int[10000];
            colors = new Color[10000];

            addMouseListener (new Proj1Listener());
            addMouseMotionListener (new Proj1Listener());
            addMouseWheelListener (new Proj1Listener());

            setBackground(Color.black);
            setPreferredSize(new Dimension(300, 200));
        
        public void paintComponent(Graphics page)
            super.paintComponent(page);
            for(Point spot : pointList)
                page.setColor(colors[c]);
                page.fillRect(spot.x-sizes[pointList.size()], spot.y-sizes[pointList.size()], sizes[pointList.size()]*2, sizes[pointList.size()]*2);
                c = 0;
            
            repaint();
            page.setColor(Color.RED);
            page.fillRect(5, 40, 30, 30);
            page.setColor(Color.BLUE);
            page.fillRect(5, 75, 30, 30);
            page.setColor(Color.GREEN);
            page.fillRect(5, 110, 30, 30);
            page.setColor(Color.WHITE);
            page.fillRect(5, 145, 30, 30);
            page.setColor(Color.WHITE);
            page.drawString("Count: " + pointList.size() + "/10000", 5, 15);
            page.drawString("Size: " + SIZE, 5, 30);
        
        private class Proj1Listener implements MouseListener, MouseMotionListener, MouseWheelListener
            public void mousePressed(MouseEvent event)
                pointList.add(event.getPoint());
                sizes[pointList.size()] = SIZE;
                repaint();
            
            public void mouseDragged(MouseEvent event)
                pointList.add(event.getPoint());
                sizes[pointList.size()] = SIZE;
                repaint();
            
            public void mouseWheelMoved(MouseWheelEvent event)
                SIZE -= event.getWheelRotation();
                repaint();
            
            public void mouseClicked(MouseEvent event)
                int x1 = event.getX();
                int y1 = event.getY();
                if(x1 > 5 && x1 < 35 && y1 > 40 && y1 < 70)
                    colors[c] = Color.RED;
                
                if(x1 > 5 && x1 < 35 && y1 > 75 && y1 < 105)
                    colors[c] = Color.BLUE;
                
                if(x1 > 5 && x1 < 35 && y1 > 110 && y1 < 140)
                    colors[c] = Color.GREEN;
                
                if(x1 > 5 && x1 < 35 && y1 > 145 && y1 < 175)
                    colors[c] = Color.WHITE;
                
            
            public void mouseReleased(MouseEvent event)
            public void mouseEntered(MouseEvent event)
            public void mouseExited(MouseEvent event)
            public void mouseMoved(MouseEvent event)
        
    

编辑: 我能够解决我的程序遇到的问题。在绘制循环之前,我必须重置几个变量。这是工作程序!

import java.util.ArrayList;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;

public class Proj1Panel extends JPanel
    public int SIZE = 5, c = 0, s = 0;
    private ArrayList<Point> pointList;
    private int[] sizes;
    private Color[] colors;
    public String colorIs = "WHITE";

    public Proj1Panel()
        pointList = new ArrayList<Point>();
        sizes = new int[1000000];
        colors = new Color[1000000];

        addMouseListener (new Proj1Listener());
        addMouseMotionListener (new Proj1Listener());
        addMouseWheelListener (new Proj1Listener());

        setBackground(Color.black);
        setPreferredSize(new Dimension(300, 200));
    
    public void paintComponent(Graphics page)
        super.paintComponent(page);
        page.setColor(Color.WHITE);
        c = 0;
        s = 0;
        for(Point spot : pointList)
            page.setColor(colors[c]);
            page.fillRect(spot.x-sizes[s], spot.y-sizes[s], sizes[s]*2, sizes[s]*2);
            c++;
            s++;
        
        repaint();
        page.setColor(Color.BLACK);
        page.fillRect(0, 0, 150, 35);
        page.setColor(Color.BLACK);
        page.fillRect(0, 35, 40, 180);
        page.setColor(Color.RED);
        page.fillRect(5, 40, 30, 30);
        page.setColor(Color.BLUE);
        page.fillRect(5, 75, 30, 30);
        page.setColor(Color.GREEN);
        page.fillRect(5, 110, 30, 30);
        page.setColor(Color.WHITE);
        page.fillRect(5, 145, 30, 30);
        page.setColor(Color.WHITE);
        page.fillRect(5, 180, 30, 30);
        page.setColor(Color.BLACK);
        page.fillRect(7, 182, 26, 26);
        page.setColor(Color.WHITE);
        page.drawString("Count: " + pointList.size() + "/1000000", 5, 15);
        page.drawString("Size: " + SIZE, 5, 30);
        page.drawString("Color: ", 65, 30);
        page.drawString(colorIs, 100, 30);
    
    private class Proj1Listener implements MouseListener, MouseMotionListener, MouseWheelListener
        public void mousePressed(MouseEvent event)
            pointList.add(event.getPoint());
            sizes[pointList.size()] = SIZE;
            repaint();
        
        public void mouseDragged(MouseEvent event)
            pointList.add(event.getPoint());
            sizes[pointList.size()] = SIZE;
            repaint();
        
        public void mouseWheelMoved(MouseWheelEvent event)
            SIZE -= event.getWheelRotation();
            repaint();
        
        public void mouseClicked(MouseEvent event)
            int x1 = event.getX();
            int y1 = event.getY();
            if(x1 > 5 && x1 < 35 && y1 > 40 && y1 < 70)
                colors[c] = Color.RED;
                colorIs = "RED";
            
            if(x1 > 5 && x1 < 35 && y1 > 75 && y1 < 105)
                colors[c] = Color.BLUE;
                colorIs = "BLUE";
            
            if(x1 > 5 && x1 < 35 && y1 > 110 && y1 < 140)
                colors[c] = Color.GREEN;
                colorIs = "GREEN";
            
            if(x1 > 5 && x1 < 35 && y1 > 145 && y1 < 175)
                colors[c] = Color.WHITE;
                colorIs = "WHITE";
            
            if(x1 > 5 && x1 < 35 && y1 > 180 && y1 < 210)
                colors[c] = Color.black;
                colorIs = "BLACK";
            
        
        public void mouseReleased(MouseEvent event)
        public void mouseEntered(MouseEvent event)
        public void mouseExited(MouseEvent event)
        public void mouseMoved(MouseEvent event)
    

【问题讨论】:

我假设它在sizes[pointList.size()] = SIZE; 上崩溃了,但你能发布堆栈跟踪吗? 你知道错误来自哪一行吗? 我返回并包含控制台摆动的错误代码。它说问题出在 paintComponent 类中的 for(Points spot : pointList) 循环中 【参考方案1】:

您永远不会在 paintComponent 方法中将用作颜色数组索引的 c 变量重置为 0。相反,它在程序开始时设置为 0 一次。因此它将单调增加,直到数组溢出。请考虑在paintComponent 的开头将其重置为0。

另外,您使用的是哪种 Point 类?它包含一些我们没有看到的数组。这里:

spot.x-sizes[pointList.size()]

编辑 我很抱歉,因为我误读了您的代码,而且我也没有很好地解释我的答案。您仍然应该增加c 变量,但您应该在paintcomponent 的开始 处将其重新设置为0。例如:

public void paintComponent(Graphics page) 
  super.paintComponent(page);
  c = 0;  // each time paintComponent starts, c should be 0
  for (Point spot : pointList) 
     page.setColor(colors[c]);
     page.fillRect(spot.x - sizes[pointList.size()], spot.y
           - sizes[pointList.size()], sizes[pointList.size()] * 2,
           sizes[pointList.size()] * 2);
     c++;  // but within the for loop, it should increment.
  
  // .... etc

或者,不要使用 for-each 循环,而是使用基本的 for 循环,这样您甚至不需要 c 变量。

【讨论】:

这消除了 ArrayOutOfBounds 错误,但现在它只保存了我的颜色数组中第一个元素的颜色。我试图到达程序将每个点保存为自己的大小和颜色的位置。有什么建议吗? @TristanWright:我们需要看看你的 Point 课程。你每次只画一个索引的点,这让我很困惑。 pointList 是在 Proj1Panel 类开头声明的 ArrayList。据我所知,MouseListener 会根据鼠标点击的位置进行检测,然后将该点保存为 pointList 中的一个元素,稍后再调用它,以及添加最后一个点后的大小。 @TristanWright:spot 是一个 Point 变量,但在查找 java.awt.Point 的 API 时,我没有说其中有任何 x-sizes 数组字段。这是让我感到困惑的一件事。 就是这样,我的教授希望pointList中的每个点都以自己对应的大小和颜色绘制在框架上,指向sizes和@987654332这两个平行数组@。我很困惑。【参考方案2】:

创建一个自定义对象以包含您进行绘画所需的信息。那就是您的自定义对象可以包含您要绘制的颜色和矩形。

请参阅Custom Painting Approaches 了解如何完成此操作的示例,然后更改您的代码以使用自定义对象。您将使用 DrawOnComponent 示例。

我的教授希望 pointList 中的每个点都以自己对应的大小和颜色绘制在框架上,指向两个平行的大小和颜色数组。

我刚刚阅读了上面的评论,所以我的建议没有帮助。但是,看示例仍然不会有什么坏处,每次您在 ArrayList 顶部添加一个“点”时,您还需要同时设置 Color 和 Size。尽管我的代码使用了 Rectangle,但您的代码也需要相同的逻辑。

另外,为什么要将一个数据结构作为 ArrayList,而将另外两个结构作为 Array。 (告诉教授)这是一个可怕的要求。 ArrayList 可以增长到任何大小,但 Arrays 是硬编码到 1000 的幻数。

【讨论】:

以上是关于绘制程序未使用并行数组正确存储大小和颜色的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 中的 UIImageView 未正确绘制

混淆矩阵颜色匹配数据大小而不是分类精度

python数据可视化--matplotlib绘制散点图

UITableView 单元格未填充 CloudKit 数据

用额外的颜色为形状上色

绘制水平条形图的给定颜色并使用 ggplot2 将未绘制区域用灰色着色