4

我在应用程序的不同位置使用JColorchooser。可以有多个可以调用 JColorChooser 的面板实例。
选择器中的“色板”面板有一个“最近的”颜色区域,它只存在于 JColorChooser 的每个实例中。我想(a)在我的应用程序中的所有选择器中使用相同的“最近”颜色,并且(b)将颜色保存到磁盘,以便这些颜色在关闭和重新启动应用程序时仍然存在。
(至少(a)可以通过在整个应用程序中使用相同的单个选择器实例来解决,但这看起来很麻烦,因为我需要非常小心附加的更改监听器,

我没有找到任何可以让我在选择器面板中设置(恢复)这些“最近”颜色的方法。所以对我来说,实现这一目标的唯一方法似乎是:

  • 序列化并保存/恢复整个选择器(选择器面板?)或
  • 从头开始创建我自己的选择器面板

这是正确的,还是我错过了什么?

顺便说一句:我还想检测选择器中的双击,但似乎很难找到将鼠标侦听器附加到的正确位置。我真的需要深入研究选择器面板的内部结构来做到这一点吗?(不,检测第二次单击相同颜色时不起作用,因为更改侦听器仅在单击不同颜色时才会触发。)

4

3 回答 3

4

正如您所注意到的,没有公共 api 可以访问 DefaultSwatchChooserPanel 中的最近颜色,即使面板本身也无法访问。

因为您需要一些逻辑/bean 来保存和重置最近的颜色(加上扩展的鼠标交互),所以滚动您自己的方式是要走的路。有关一些指导,请查看样本面板的实现(咳嗽...... c&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 调用该操作。

于 2012-06-18T10:07:29.543 回答
2

您可以使用该JColorChooser.createDialog方法 - 其中一个参数是 a JColorChooser。使用 的静态实例JColorChooser并使其成为Dialog modal- 这样,一次只显示一个颜色选择器。

createDialog方法还将ActionListenersOK 和 Cancel 按钮作为参数。因此,实际上不必管理侦听器。当然,这不会在应用程序的调用中保留最近的颜色,只是在当前应用程序中保留最近的颜色。

于 2016-12-23T18:32:43.410 回答
1

这是使用反射的解决方法 - 只要底层实现不改变,它就会起作用。假设你有一个 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;
        }

    }
于 2018-10-22T03:34:15.077 回答