0

我正在为我的 AP 化学课开发分子查看器。我为每个元素分配了不同的颜色。例如,氢是白色的,碳是黑色的,氧是红色的。

当我调用要渲染的新元素时,它看起来像这样:

newAtom(x, y, z, color);

然后渲染原子。

因为有一百多种元素,所以有很多不同的颜色。

我应该为所有这些颜色制作单独的课程吗?例如:

public class AtomColors {

    // By atomic number
    public final static Color H = new Color(1, 1, 1, 1);
    public final static Color He = new Color(1, 0.5f, 1, 1);
    public final static Color Li = new Color(0.5f, 1, 1, 1);
    public final static Color Be = new Color(1, 1, 1, 0.5f);
}

我不确定是否有标准方式或这样做,哪种方式最有效。那是我的问题。这有更好的方法吗?

4

6 回答 6

7

我认为Enum最适合这里。枚举用于表示语言提供的结构中的相关常量。

您可以表示如下颜色:

public enum ColorEnum {
    H(1, 1, 1, 1),
    He(1, 0.5f, 1, 1),
    Li(0.5f, 1, 1, 1),
    Be(1, 1, 1, 0.5f);

    private final float cyan;
    private final float magenta;
    private final float yellow;
    private final float black;

    EnumTest(float cyan, float megenta, float yellow, float black) {
        this.cyan = cyan;
        this.megenta = megenta;
        this.yellow = yellow;
        this.black = black;
    }

    public float getCyan() { return cyan; }
    public float getMegenta() { return megenta; }
    public float getYellow() { return yellow; }
    public float getBlack() { return black; }

    public Color getColor() {
            new Color(cyan, megenta, yellow, black);
    }
}

并像这样使用它

newAtom(x, y, z, ColorEnum.He);

我建议,要获取有关此主题的更多信息,请参阅

于 2013-09-23T02:38:11.280 回答
1

你的代码很好。使用枚举很好。但是,如果您想让您的用户重新配置颜色,那将因为您的变量是最终的事实而变得困难。此外,如果您想让用户重新配置颜色,则不应将颜色存储在枚举中,因为作为最佳实践,枚举应该是不可变的。如果您想让用户以某种方式覆盖您的默认配色方案,则代码可能如下所示。

public enum Element
{
    Ac("Actinium", 89),
    Ag("Silver", 47),
    Al("Aluminum", 13); 
    // etcetera

    private final String americanEnglishName;
    private final int atomicNumber;

    private Element(String americanEnglishName, int atomicNumber)
    {
        this.americanEnglishName = americanEnglishName;
        this.atomicNumber = atomicNumber;
    }

    public String getAmericanEnglishName()
    {
        return americanEnglishName;
    }

    public int getAtomicNumber()
    {
        return atomicNumber;
    }
}

class ApplicationSettings
{
    private static final Map<Element, Color> DEFAULT_COLORING;
    static
    {
        EnumMap<Element, Color> colorMap = 
            new EnumMap<Element, Color>(Element.class);
        colorMap.put(Element.Ac, new Color(1, 2, 3));
        colorMap.put(Element.Ag, Color.green);
        colorMap.put(Element.Al, Color.blue);
        // etcetera

        DEFAULT_COLORING = Collections.unmodifiableMap(colorMap);
    }

    private Map<Element, Color> _userPreferredColors = DEFAULT_COLORING;

    public Map<Element, Color> getUserPreferredColors()
    {
        return _userPreferredColors;
    }

    public void setUserPreferredColors(Map<Element, Color> userPreferredColors)
    {
        _userPreferredColors = userPreferredColors;
    }
}

class Application
{
    private ApplicationSettings _settings;

    public Application(ApplicationSettings settings)
    {
        _settings = settings;
    }

    private void run()
    {
        for(Element element : Element.values())
        {
            Color color = _settings.getUserPreferredColors().get(element);
            System.out.println(element.getAmericanEnglishName() + "=" + color);
        }

    }

    public static void main(String[] args) 
    {
        ApplicationSettings settings = new ApplicationSettings();
        Application app = new Application(settings);
        app.run();
    }    
}
于 2013-09-23T03:17:38.433 回答
0

我假设每种颜色都有一个相关的数字,您需要将其传递给分子查看器。

您可以创建一个以元素名称(或颜色名称)HashMap ,其值为颜色编号

于 2013-09-23T02:39:52.077 回答
0

似乎颜色是您设计中原子的属性。从面向对象设计的角度来看,我会让每个Atom类都有一个Color存储其颜色的属性。然后该newAtom方法将获取一个位置和一个Atom要绘制的对象,它会访问 的 color 属性Atom来确定使用哪种颜色绘制它。

如果您想轻松保证原子的唯一颜色,我会使用质子数来生成颜色,例如,保持绿色和蓝色值不变,并根据质子数生成不同的红色值(0 到 255 )。

于 2013-09-23T02:42:44.883 回答
0

我不确定是否有标准方式或这样做,哪种方式最有效。

没有“标准”方式,但你这样做的方式应该没问题。

这样做没有效率问题。(事实上​​,无论你怎么做,效率都不太可能成为问题。性能瓶颈很可能在 3D 几何和渲染代码中。)

唯一的障碍是这种方法(或多或少)迫使您对数据结构进行非规范化;即在原子实例上存储颜色,而不是元素。@MikeClark 的回答清楚地说明了这一点。(@JayPatel 的回答似乎也是尝试这样做......虽然他的造型有一些问题。从什么时候开始“氦气”成为一种颜色??)

这有更好的方法吗?

Map<String, Color>一种替代方法是为每个命名元素填充颜色。这可能更灵活,特别是如果您希望能够动态添加新元素和/或更改元素颜色(即不更改代码)。

可能还有其他人。


我的建议是不要“过度思考”。只需以一种对您来说似乎很自然的方式实现它,并且如果您的代码由于某些“非最佳”数据结构设计决策而开始变得笨拙/重复/混乱......重新审视这些决策。

于 2013-09-23T02:44:46.233 回答
0

任何时候,只要您有一个在编译时已知的常量列表(例如元素周期表中的元素),这就是使用枚举的正确时机。枚举对您来说是实例控制的,并且开箱即用是类型安全的。随着您的需求增长,您可以灵活地添加枚举方法甚至是特定于常量的方法。

此外,已经有优化的集合类可以简化 Enum 常量集合的处理:EnumSet(用于可以表示颜色组合的枚举集)和 EnumMap,用于处理映射到特定枚举常量的数据集合。

于 2013-09-23T03:20:38.570 回答