如何分配和处理SWT中的动态颜色?

时间:2012-11-16 02:55:27

标签: java colors swt

我有时需要在SWT中动态生成颜色。以一个视图为例,该视图显示红色 - 绿色不同颜色的0-1之间的分数。可能有其他类似的观点有不同的颜色:

class ScoreView {
    private Canvas canvas;
    private List<Item> items = new ArrayList<Item>();

    public ScoreView(Composite parent) {
        canvas = new Canvas(parent, SWT.NONE);

        canvas.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent event) {
                GC gc = event.gc;

                int x = 0;
                for(Item item:items) {
                    int shade = (int)(item.getScore() * 255.0);

                    Color color = new Color(Display.getCurrent(), shade, 255-shade, 0);
                    gc.setBackground(color);
                    gc.fillRectangle(x, 0, 50, 50);
                    x += 50;
                }
            }
        });
    }

    public void setItems(List<Item> items) {
        this.items = items;
        canvas.redraw();
    }
}

在SWT中,您应该始终释放资源。来自http://www.eclipse.org/articles/Article-SWT-Color-Model/swt-color-model.htm

  

颜色包含必须分配和释放的OS资源。因此,有必要处理您创建的每种颜色。

那么处理颜色的最佳方式是什么?

来自http://www.eclipse.org/articles/swt-design-2/swt-design-2.html

  

如果你在一个小部件中使用图形资源 - 例如,widget.setFont(font) - 通常最好在它们被使用的小部件被清理时清理它们,这样你就可以将一个dispose监听器挂钩了插件...

因此,我可以跟踪我分配的每种颜色,并将它们放置在画布或外壳上的DisposeListener中。但是从同一个链接:

  

当程序退出时,操作系统释放程序的所有资源。为什么不依靠这个呢?操作系统资源不是无限的。如果您的程序不再释放资源,因为它们不再需要,它可能会耗尽资源。它还可能导致其他程序耗尽资源。所以等到程序退出以释放资源通常是一个坏主意。

看起来我没有获得任何东西,因为即使颜色被处理掉,它们也会在退出处被放置(视图持续程序的生命周期)。

我认为我不能直接在PaintListener中处理颜色,因为它们在显示时仍然被GC使用,所以我必须记住正在使用的颜色如果在该电话中没有再次使用它们,请将它们丢弃到下一个绘画调用中?

如果我管理它,如果只有几种颜色,还有另一个问题。由于颜色分配的顺序,我可以渲染许多红色,然后用尽颜色,并且不能显示任何颜色的绿色。那么在这种情况下,最好预先分配一些我可能需要在程序开头的颜色(如调色板)?我应该分配多少以及按什么顺序分配?这意味着永远不会处理这些颜色。

此外,有什么方法可以随时了解有多少种颜色?其他正在运行的程序是否会消除可用的颜色数量?

3 个答案:

答案 0 :(得分:5)

Eclipse RCP通过全局ColorRegistry处理此问题。

通过使用它,可以避免在应用程序启动时进行资源预分配。 当您需要资源时,可以查询全局注册表。 如果它不可用,则分配并在全局注册表中注册。

private static final String SHADE = "shadedcolor";

Color color = null;
if (!JFaceResources.getColorRegistry().hasValueFor(SHADE)) {
    color = new Color(Display.getCurrent(), shade, 255-shade, 0);
    JFaceResources.getColorRegistry().put(SHADE, color);
} else {
    color = JFaceResources.getColorRegistry().get(SHADE);
}

资源将在应用程序退出时解除分配。

答案 1 :(得分:3)

除了之前的答案,您还可以使用系统颜色。这些颜色不需要处理。

您可以致电Display#getSystemColor(int)

来访问它们
Display display = Display.getCurrent();
Color blue = display.getSystemColor(SWT.COLOR_BLUE);

有关可用颜色的列表,请转到:Javadoc of SWT

您可以使用以SWT.COLOR_开头的任何内容。

答案 2 :(得分:1)

paintControl方法中,创建颜色,使用它并处理它。

Color color = new Color(Display.getCurrent(), shade, 255-shade, 0);
gc.setBackground(color);
gc.fillRectangle(x, 0, 50, 50); // this call renders it then you can dispose the color
color.dispose();
这种方法的问题是,创建/销毁资源是一项昂贵的操作。这就是为什么你需要缓存它。

我建议你在shadeColor中将Item作为属性。当分数发生变化时,处置现有shadeColor并创建新的shareColor。在处置/移除shareColor时处理Item