Вопрос по swing, java – JColorChooser: сохранение / восстановление последних цветов на панели «Образцы»

2

Я используюJColorchooser в разных местах в приложении. Может быть несколько экземпляров панели, которые могут вызывать JColorChooser.
& Quot; Образцы & quot; Панель в селекторе имеет площадь"recent" colors, который сохраняется только в каждом экземпляре JColorChooser. я бы хотел(a) have the same "recent" colors in all my choosers в моем приложении, и(b) to save the colors to disk так что эти цвета выжить близко и перезапустить приложение.
(По крайней мере (а) можно решить, используя один и тот же экземпляр выбора во всем приложении, но это выглядит громоздко, потому что мне нужно быть очень осторожным с подключенными списками изменений и добавлением / удалением панели выбора в / из различных диалоговых окон). .)

Я не нашел никакого метода, который позволил бы мне установить (восстановить) эти & quot; недавние & quot; цвета на панели выбора. Поэтому мне кажется, что единственными путями достижения этого могут быть:

serialize and save / restore the whole chooser (chooser panel?) or create my own chooser panel from scratch

Это правильно, или я что-то упустил?

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

Ваш Ответ

3   ответа
4

Как вы заметили, нет общедоступного API для доступа к последним цветам в DefaultSwatchChooserPanel, даже сама панель недоступна.

Поскольку вам понадобится некоторая логика / компонент, который в любом случае будет содержать и сбрасывать последние цвета (плюс расширенное взаимодействие с мышью), переход на собственное - это путь. Для получения некоторых рекомендаций взгляните на реализацию панели образцов (кашель ... c & amp; p, что вам нужно, и измените то, что вам не нужно). В принципе, что-то вроде

// a bean that keeps track of the colors
public static class ColorTracker extends AbstractBean {

    private List<Color> colors = new ArrayList<>();

    public void addColor(Color color) {
        List<Color> old = getColors();
        colors.add(0, color);
        firePropertyChange("colors", old, getColors());
    }

    public void setColors(List<Color> colors) {
        List<Color> old = getColors();
        this.colors = new ArrayList<>(colors);
        firePropertyChange("colors", old, getColors());
    }

    public List<Color> getColors() {
        return new ArrayList<>(colors);
    }
}

// a custom SwatchChooserPanel which takes and listens to the tracker changes
public class MySwatchChooserPanel ... {

   ColorTracker tracker;

   public void setColorTracker(....) {
       // uninstall old tracker 
       ....
       // install new tracker
       this.tracker = tracker;
       if (tracker != null) 
           tracker.addPropertyChangeListener(.... );
       updateRecentSwatchPanel()
   }

   /** 
    * A method updating the recent colors in the swatchPanel
    * This is called whenever necessary, specifically after building the panel,
    * on changes of the tracker, from the mouseListener
    */
   protected void updateRecentSwatchPanel() {
       if (recentSwatchPanel == null) return;
       recentSwatchPanel.setMostRecentColors(tracker != null ? tracker.getColors() : null);
   }

// the mouseListener which updates the tracker and triggers the doubleClickAction
// if available
class MainSwatchListener extends MouseAdapter implements Serializable {
    @Override
    public void mousePressed(MouseEvent e) {
        if (!isEnabled())
            return;
        if (e.getClickCount() == 2) {
            handleDoubleClick(e);
            return;
        }

        Color color = swatchPanel.getColorForLocation(e.getX(), e.getY());
        setSelectedColor(color);
        if (tracker != null) {
            tracker.addColor(color);
        } else {
            recentSwatchPanel.setMostRecentColor(color);
        }
    }

    /**
     * @param e
     */
    private void handleDoubleClick(MouseEvent e) {
        if (action != null) {
            action.actionPerformed(null);
        }
    }
}


} 

// client code can install the custom panel on a JFileChooser, passing in a tracker
private JColorChooser createChooser(ColorTracker tracker) {
    JColorChooser chooser = new JColorChooser();
    List<AbstractColorChooserPanel> choosers = 
            new ArrayList<>(Arrays.asList(chooser.getChooserPanels()));
    choosers.remove(0);
    MySwatchChooserPanel swatch = new MySwatchChooserPanel();
    swatch.setColorTracker(tracker);
    swatch.setAction(doubleClickAction);
    choosers.add(0, swatch);
    chooser.setChooserPanels(choosers.toArray(new AbstractColorChooserPanel[0]));
    return chooser;
}

Что касается обработки doubleClick: улучшите swatchChooser, чтобы он выполнял действие, и при необходимости вызывайте это действие из mouseListener.

1

Вы можете использоватьJColorChooser.createDialog метод - один из параметровJColorChooser, Используйте статический экземплярJColorChooser и сделать этоDialog modal - таким образом, только один цвет выбора отображается одновременно.

createDialog метод также занимаетActionListeners в качестве параметров для кнопки ОК и Отмена. Таким образом, действительно не нужно управлять слушателями. Конечно, это не сохраняет последние цвета при вызовах приложения, просто сохраняет последние цвета в текущем приложении.

0

Вот обходной путь, использующий отражение - он будет работать при условии, что базовая реализация не изменится. Предполагая, что у вас есть JColorChooser, добавьте в него свои последние цвета следующим образом:

    final JColorChooser chooser = new JColorChooser(Color.white);

    for (AbstractColorChooserPanel p : chooser.getChooserPanels()) {

        if (p.getClass().getSimpleName().equals("DefaultSwatchChooserPanel")) {

            Field recentPanelField = p.getClass().getDeclaredField("recentSwatchPanel");
            recentPanelField.setAccessible(true);

            Object recentPanel = recentPanelField.get(p);

            Method recentColorMethod = recentPanel.getClass().getMethod("setMostRecentColor", Color.class);
            recentColorMethod.setAccessible(true);

            recentColorMethod.invoke(recentPanel, Color.BLACK);
            recentColorMethod.invoke(recentPanel, Color.RED);

            //add more colors as desired

            break;
        }

    }

Похожие вопросы