关于Java:用额外颜色来着色形状

Coloring shapes in order with extra colors

我正在制作一个程序,允许用户在屏幕上绘制多个形状并选择所需的颜色。目前我有九种预设颜色供用户选择。我计划使用JColorChooser允许用户选择不同的颜色。但是,我无法找到一种方法来存储可能选择的额外颜色,以便在重新绘制图形时,它们将保持与绘制时相同的颜色。

我想出了一种方法,按照绘制的顺序和绘制的颜色重新绘制形状,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
private List<Shape> shapeList = new ArrayList<Shape>();
private List<Integer> opNumList = new ArrayList<Integer>();

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int index = 0;
    Graphics2D g2 = (Graphics2D) g.create();

    if (!opNumList.isEmpty()) {
        for (Shape s : shapeList) {
            switch (opNumList.get(index))
                case  0: g2.setColor(Color.red);    g2.draw(s); break;
                case  1: g2.setColor(Color.red);    g2.fill(s); break;
                case  2: g2.setColor(Color.orange); g2.draw(s); break;
                case  3: g2.setColor(Color.orange); g2.fill(s); break;
                case  4: g2.setColor(Color.yellow); g2.draw(s); break;
                case  5: g2.setColor(Color.yellow); g2.fill(s); break;
                case  6: g2.setColor(Color.green);  g2.draw(s); break;
                case  7: g2.setColor(Color.green);  g2.fill(s); break;
                case  8: g2.setColor(Color.blue);   g2.draw(s); break;
                case  9: g2.setColor(Color.blue);   g2.fill(s); break;
                case 10: g2.setColor(purple);       g2.draw(s); break;
                case 11: g2.setColor(purple);       g2.fill(s); break;
                case 12: g2.setColor(brown);        g2.draw(s); break;
                case 13: g2.setColor(brown);        g2.fill(s); break;
                case 14: g2.setColor(Color.white);  g2.draw(s); break;
                case 15: g2.setColor(Color.white);  g2.fill(s); break;
                case 16: g2.setColor(Color.black);  g2.draw(s); break;
                case 17: g2.setColor(Color.black);  g2.fill(s); break;
                default: return;
            }
            index++;
        }
    }
}

@Override
public void mouseReleased(MouseEvent ev) {
    if (color == Color.red) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(0);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(1);
    }

    if (color == Color.orange) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(2);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(3);
    }

    if (color == Color.yellow) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(4);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(5);
    }

    if (color == Color.green) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(6);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(7);
    }

    if (color == Color.blue) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(8);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(9);
    }

    if (color == purple) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(10);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(11);
    }

    if (color == brown) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(12);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(13);
    }

    if (color == Color.white) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(14);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(15);
    }

    if (color == Color.black) {
        if (toolNum == LINE || (toolNum == RECTANGLE && !cbFillItem.isSelected()) || (toolNum == OVAL && !cbFillItem.isSelected()))
            opNumList.add(16);
        if ((toolNum == RECTANGLE || toolNum == OVAL) && cbFillItem.isSelected())
            opNumList.add(17);
    }
    repaint();
}

因此,当用户绘制形状时,它存储在Shape对象的ArrayList中。整数存储在一个单独的列表中,该列表基于所绘制的形状及其颜色。然后,当程序重新绘制所有形状时,它将遍历列表中的每个形状,并为这些形状赋予绘制它们所用的颜色,并在必要时填充它们。

现在,我想知道的是一种将这些颜色转移到自己的List或者甚至可能是Map的方法,以避免创建大量的Color对象并添加到已经很长的代码列表中,这样,如果用户决定使用其他颜色,程序将知道哪些颜色属于什么形状。因此,例如,如果用户决定绘制一个颜色为128128128的填充矩形;当程序重新绘制形状时,它将知道该矩形已被填充,并且被着色为特定的灰色阴影。但我还没有走那么远,现在我正在努力寻找一种解决方案,它只适用于我目前拥有的九种颜色。

有人知道怎么做吗?


这需要一些研究和环顾四周,但我最终找到了解决问题的方法。

最初我考虑使用Map,这样我就可以添加一个键值对,只要我可以访问地图的所有键(实现Shape接口的对象),我就可以轻松地将它们与它们的值(Color对象)进行配对。所以我想到了这个:

1
Map<Shape,Color> map = new HashMap<Shape,Color>();

这允许我存储用户绘制的任何形状以及使用的相应颜色。但现在我必须找到一种方法,使用for循环检索所有存储的形状,以便重新绘制它们。做了一点研究,我发现了这个答案,它显示了如何使用所述循环迭代Map。因此,我可以用以下内容取代switch声明:

1
2
3
4
5
6
7
for (Entry<Shape,Color> entry : map.entrySet()) {
    Shape shape = entry.getKey();
    Color color = entry.getValue();

    g2.setColor(color);
    g2.draw(shape);
}

然而,我遇到了另一个问题:键值配对不整齐,这意味着当某些形状以前在它们后面时,它们会随机出现在其他形状的上面,反之亦然。因此,更多的研究帮助我确定,我应该使用LinkedHashMap,它保留了存储键值对的顺序:

1
Map<Shape,Color> map = new LinkedHashMap<Shape,Color>();

一点点的尝试和错误帮助我认识到,由于保证了键值对的顺序,所以我总是可以使用opNumList来确定给定的形状应该是开放的还是填充的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int index = 0;
for (Entry<Shape,Color> entry : map.entrySet()) {
    Shape shape = entry.getKey();
    Color color = entry.getValue();

    g2.setColor(color);
    if (!opNumList.isEmpty()) {
        if (opNumList.get(index) == 0)
            g2.draw(shape);
        if (opNumList.get(index) == 1)
            g2.fill(shape);
    }
    index++;
}