【问题标题】:JColorChooser: Save/restore recent colors in Swatches panelJColorChooser:在色板面板中保存/恢复最近的颜色
【发布时间】:2012-06-03 08:49:39
【问题描述】:

我在应用程序的不同位置使用 JColorchooser。可以有多个可以调用 JColorChooser 的面板实例。
选择器中的“色板”面板有一个“最近”颜色区域,该区域仅在 JColorChooser 的每个实例中持续存在。我想 (a) 在我的应用程序中的所有选择器中使用相同的“最近”颜色,并且 (b) 将颜色保存到磁盘 以便这些颜色在关闭并重新启动应用程序后幸存下来。
(至少(a)可以通过在整个应用程序中使用相同的单个选择器实例来解决,但这看起来很麻烦,因为我需要非常小心附加的更改监听器,以及在各种对话框中添加/删除选择器面板.)

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

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

这是正确的,还是我遗漏了什么?

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

【问题讨论】:

    标签: java swing mouselistener jcolorchooser


    【解决方案1】:

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

    因为您需要一些逻辑/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 调用该操作。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 2021-01-10
          • 2022-01-22
          • 1970-01-01
          • 1970-01-01
          • 2019-09-07
          • 2013-08-26
          • 2019-04-27
          • 2013-09-05
          • 2011-02-13
          相关资源
          最近更新 更多