Java Swing модульная цветовая схема

Я настраиваю крупномасштабный графический пользовательский интерфейс (больше, чем все, что я делал раньше) с помощью Java-инструментария Swing, и я хотел бы настроить свою собственную цветовую схему для рисования цветов, чтобы все определения цвета были в одном месте. Для этого я решил создать псевдостатический класс верхнего уровня с именем ColorPalette(применяется из /questions/5071241/staticheskie-klassyi-v-java/5071260#5071260 поста), который содержит SchemeEnum где программист устанавливает цветовую схему для всего графического интерфейса.

Я хотел бы, чтобы выбор цвета был независимым от знания цветовой схемы. Кто-нибудь знает шаблон дизайна или эффективный способ сделать это? Я не совсем уверен, что моя текущая установка - лучший способ реализовать это, но я хотел бы создать модульную конструкцию, где было бы не навязчиво добавлять больше ColorEnums или же SchemeEnums (во время компиляции, а не во время выполнения).

Для ясности, я хочу, чтобы программист мог просто выбрать ColorEnum и получить обратно java.awt.Color объект на основе ColorEnum и определенный SchemeEnum,

Например:

        // Use the BASIC color scheme
        ColorPalette.setCurrentScheme(ColorPalette.SchemeEnum.BASIC);

        // Set button backgrounds
        testButton.setBackground(ColorPalette.ColorEnum.DARK_RED.getColor());
        testButton2.setBackground(ColorPalette.ColorEnum.BLUE.getColor());

должен вернуть разные Color чем объекты

        // Use the DARK color scheme
        ColorPalette.setCurrentScheme(ColorPalette.SchemeEnum.DARK);

        // Set button backgrounds
        testButton.setBackground(ColorPalette.ColorEnum.DARK_RED.getColor());
        testButton2.setBackground(ColorPalette.ColorEnum.BLUE.getColor());

потому что у них разные SchemeEnums даже если они запрашивают тот же цвет от ColorPalette, Таким образом, изменяя SchemeEnum меняет каждый цвет в графическом интерфейсе с изменением кода в одну строку (или даже можно изменить цвета во время выполнения).

Я слышал, что HashTables используются для хранения больших объемов данных, таких как эта, но я не знаю, как они работают. Может ли это применяться здесь?

Вот мой код до сих пор. Заранее спасибо!

package common.lookandfeel;

import java.awt.Color;

/**
 * Class which contains the members for the color scheme used throughout the project.
 * <p>This class is essentially static (no constructor, class is final, all members static) and
 * should not be instantiated.
 */
public final class ColorPalette
{
    /**
     * The list of color schemes to choose from.
     */
    public static enum SchemeEnum
    {
        BASIC, DARK, METALLIC
    }

    /**
     * The list of color descriptions to choose from.
     */
    public static enum ColorEnum
    {
        LIGHT_RED(256,0,0), RED(192,0,0), DARK_RED(128,0,0),
        LIGHT_GREEN(0,256,0), GREEN(0,192,0), DARK_GREEN(0,128,0),
        LIGHT_BLUE(0,0,256), BLUE(0,0,192), DARK_BLUE(0,0,128),
        LIGHT_ORANGE(256,102,0), ORANGE(256,102,0), DARK_ORANGE(192,88,0),
        LIGHT_YELLOW(256,204,0), YELLOW(256,204,0), DARK_YELLOW(192,150,0),
        LIGHT_PURPLE(136,0,182), PURPLE(102,0,153), DARK_PURPLE(78,0,124);

        private int red;
        private int green;
        private int blue;

        private ColorEnum(int r, int g, int b)
        {
            this.red = r;
            this.green = g;
            this.blue = b;
        }

        /**
         * Get the selected color object for this Enum.
         * @return The color description as a Color object.
         */
        public Color getColor()
        {
            // WANT TO RETURN A COLOR BASED ON currentScheme
            return new Color(red, green, blue);
        }
    }

    private static SchemeEnum currentScheme = SchemeEnum.BASIC;

    /**
     * Default constructor is private to prevent instantiation of this makeshift 'static' class.
     */
    private ColorPalette()
    {
    }

    /**
     * Get the color scheme being used on this project.
     * @return The current color scheme in use on this project.
     */
    public static SchemeEnum getCurrentScheme()
    {
        return currentScheme;
    }

    /**
     * Set the overall color scheme of this project.
     * @param currentPalette The color scheme to set for use on this project.
     */
    public static void setCurrentScheme(SchemeEnum cp)
    {
        currentScheme = cp;
    }

    /**
     * Main method for test purposes only.  Unpredictable results.
     * @param args Command line arguments.  Should not be present.
     */
    public static void main(String[] args)
    {
        // Declare and define swing data members
        JFrame frame = new JFrame("Test Environment");
        CustomButton testButton = new CustomButton ("Hello World");
        CustomButton testButton2 = new CustomButton ("I am a button!");

        // Use a particular color scheme
        ColorPalette.setCurrentScheme(ColorPalette.SchemeEnum.BASIC);

        // Set button backgrounds
        testButton.setBackground(ColorPalette.ColorEnum.DARK_RED.getColor());
        testButton2.setBackground(ColorPalette.ColorEnum.BLUE.getColor());

        // Place swing components in Frame
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(testButton, BorderLayout.NORTH);
        frame.getContentPane().add(testButton2, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);

        // Set allocated memory to null
        frame = null;
        testButton = null;
        testButton2 = null;

        // Suggest garbage collecting to deallocate memory
        System.gc();
    }
}

2 ответа

Решение

Это выглядит и звучит так, как будто вам просто нужно составить SchemeEnum, чтобы он состоял из ColorEnums, точно так же, как вы создали ColorEnum из значений rgb.

public static enum SchemeEnum
{
    // Don't really know what colors you actually want
    BASIC(ColorEnum.RED, ColorEnum.GREEN, ColorEnum.ORANGE),
    DARK(ColorEnum.DARK_RED, ColorEnum.DARK_GREEN, ColorEnum.DARK_ORANGE),
    METALLIC(ColorEnum.LIGHT_RED, ColorEnum.LIGHT_GREEN, ColorEnum.LIGHT_ORANGE);

    // nor know how many colors make up a scheme
    public ColorEnum mainColor;
    public ColorEnum secondaryColor;
    public ColorEnum borderColor;

    private SchemeEnum(ColorEnum mainColor, ColorEnum secondaryColor, 
                       ColorEnum borderColor)
    {
        this.mainColor = mainColor;
        this.secondaryColor = secondaryColor;
        this.borderColor = borderColor;
    }
}

Затем используйте код, подобный следующему, где цвета основаны на выбранной схеме:

testButton.setBackground(ColorPalette.getCurrentScheme().mainColor.getColor());

Прежде чем вы заново изобретаете колесо, Swing основан на подключаемом интерфейсе API внешнего вида, см. Раздел "Изменение внешнего вида".

Правильный способ - определить свой внешний вид и загрузить его. Поскольку вы хотите предоставить переменное количество изменений, вероятно, было бы лучше использовать что-то вроде Synth. Это позволяет вам определять каскадные свойства для объектов и также наследовать от других свойств (чтобы вы могли разработать базовый набор свойств, а затем изменять только те свойства, которые вам нужны в каждом последующем виде).

Обманным способом было бы изменить UIManager непосредственно, изменяя различные свойства, используемые текущим внешним видом. Это иногда проще, если вы хотите выполнить небольшие изменения.

В любом случае, это повлияет на ВСЕ компоненты, созданные вашим приложением, без необходимости что-либо делать, кроме изменения внешнего вида при запуске.

Другие вопросы по тегам