【问题标题】:Creating custom JComponent with JLayer over JProgressBar在 JProgressBar 上使用 JLayer 创建自定义 JComponent
【发布时间】:2013-11-27 19:54:26
【问题描述】:

我正在尝试创建一个使用 JLayer 类的自定义 JProgressBar,以便它可以根据情况使用不同的颜色,例如 this solution。问题是我想将它包装为某种 JComponent,因为它使它更易于管理。我会将它公开为自定义的 JLayer,但该类是密封的,所以什么都不做。

我尝试将其设为 JComponent,但屏幕上没有绘制任何内容(可能是因为我不知道如何制作包含其他组件的自定义 JComponent?)。我尝试了一个 JFrame,它可以工作,但大小都是错误的,可能是因为进度条使用的是我制作的 JFrame 的布局管理器,而不是包含 JFrame 的布局管理器。我已经尝试过绘制的 JProgressBar,但是我无法返回 JLayer 并保留正确的层次结构,而无需在构造函数之后调用额外的方法,这看起来并不优雅。

这是我的示例代码,主要基于我上面链接的问题中的代码:

public class Test {
    public JComponent makeUI() {
        final BoundedRangeModel model = new DefaultBoundedRangeModel();
        model.setValue(20);

        final JPanel p = new JPanel(new GridLayout(4, 1, 12, 12));
        p.setBorder(BorderFactory.createEmptyBorder(24,24,24,24));

        // This does not draw
        final ColorProgressBar pb4 = new ColorProgressBar(model);
        p.add(pb4);

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(p, BorderLayout.NORTH);
        return panel;
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
                createAndShowGUI();
            }
        });
    }
    public static void createAndShowGUI() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch(Exception e) {
            e.printStackTrace();
        }
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new Test().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ColorProgressBar extends JComponent {
    private static final long serialVersionUID = -1265489165072929352L;

    private BlockedColorLayerUI colorUI = new BlockedColorLayerUI();
    private JLayer<JProgressBar> layer;
    private JProgressBar bar;
    private PropertyChangeSupport supporter = new PropertyChangeSupport(new WeakReference<ColorProgressBar>(this));

    public ColorProgressBar(BoundedRangeModel model) {
        bar = new JProgressBar(model);
        layer = new JLayer<JProgressBar>(bar, colorUI);
        this.add(layer);
    }

    public Color getColor() {
        if (colorUI == null)
            return null;

        return colorUI.color;
    }

    public void setColor(Color color) {
        Color oldColor = colorUI.color;
        colorUI.color = color;
        supporter.firePropertyChange("color", oldColor, color);
    }

    @Override
    public void paintComponents(Graphics g) {
        layer.paintComponents(g);
    }

    class BlockedColorLayerUI extends LayerUI<JProgressBar> {
        public Color color = null;
        private BufferedImage bi;
        private int prevw = -1;
        private int prevh = -1;
        @Override public void paint(Graphics g, JComponent c) {
            if(color != null) {
                JLayer<?> jlayer = (JLayer<?>)c;
                JProgressBar progress = (JProgressBar)jlayer.getView();
                int w = progress.getSize().width;
                int h = progress.getSize().height;

                if(bi==null || w!=prevw || h!=prevh) {
                    bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
                }
                prevw = w;
                prevh = h;

                Graphics2D g2 = bi.createGraphics();
                super.paint(g2, c);
                g2.dispose();

                Image image = c.createImage(
                        new FilteredImageSource(bi.getSource(),
                                new ColorFilter(color)));
                g.drawImage(image, 0, 0, c);
            } else {
                super.paint(g, c);
            }
        }
    }
    class ColorFilter extends RGBImageFilter {
        Color color;

        public ColorFilter(Color color) {
            this.color = color;
        }

        @Override public int filterRGB(int x, int y, int argb) {
            int r = (int)((argb >> 16) & 0xff);
            int g = (int)((argb >>  8) & 0xff);
            int b = (int)((argb      ) & 0xff);
            return (argb & color.getRGB()) | (g<<16) | (r<<8) | (b);
        }
    }
}

有人知道我哪里出错了吗?谢谢!

编辑:我稍微精简了示例并对其进行了修改以更好地表达我的问题。很抱歉造成混乱。

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖SSCCE
  • 我不完全确定如何缩短它并使其行为可诊断。如果您有任何建议,请随时分享;否则它肯定是独立的和可编译的。
  • “我不完全确定如何让它更短” SSCCE 不仅仅是“短”。回去再读一遍。另外 WTF UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 是否与问题有关?!?您应该已经尝试将其删除。
  • 删除该行代码的效果实际上更难看到。应用颜色叠加效果时,默认的 Swing 外观几乎不会在视觉上发生变化。我想我可以使用其中一个打包的 LaF 而不是系统的,但老实说,我不认为有人会发现那一行代码如此令人反感。
  • “通过删除那行代码的效果实际上更难看到。” 你知道原生PLAF在不同的操作系统上是不同的吗? “单行代码” &lt;/head-desk&gt; 不要将其视为“单个”LOC,而是'第一个' LOC。

标签: java swing jcomponent jprogressbar jlayer


【解决方案1】:

您可能需要致电super(model);p.add(pb4.layer);

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.beans.*;
import java.lang.ref.WeakReference;
import javax.swing.*;
import javax.swing.plaf.LayerUI;

public class Test2 {
    public JComponent makeUI() {
        final BoundedRangeModel model = new DefaultBoundedRangeModel();
        final JPanel p = new JPanel(new GridLayout(4, 1, 12, 12));
        p.setBorder(BorderFactory.createEmptyBorder(24,24,24,24));

        final JProgressBar pb1 = new JProgressBar(model);
        pb1.setStringPainted(true);
        p.add(pb1);
        final JProgressBar pb2 = new JProgressBar(model);
        pb2.setStringPainted(true);
        p.add(pb2);

        p.add(new JProgressBar(model));
        final ColorProgressBar pb4 = new ColorProgressBar(model);
        p.add(pb4.layer);

        JPanel box = new JPanel();
        box.add(new JButton(new AbstractAction("+10") {
            private int i = 0;
            @Override public void actionPerformed(ActionEvent e) {
                model.setValue(i = (i>=100) ? 0 : i + 10);
            }
        }));
        //http://msdn.microsoft.com/en-us/library/windows/desktop/aa511486.aspx
        box.add(new JCheckBox(new AbstractAction(
                "<html>Turn the progress bar red<br />"+
                        " when there is a user recoverable condition<br />"+
                " that prevents making further progress.") {
            @Override public void actionPerformed(ActionEvent e) {
                boolean b = ((JCheckBox)e.getSource()).isSelected();
                pb2.setForeground(b? new Color(255,0,0,100) : new Color(255,255,0,100));
                if (b)
                    pb4.setColor(Color.RED);
                else
                    pb4.setColor(Color.YELLOW);
                p.repaint();
            }
        }));

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(p, BorderLayout.NORTH);
        panel.add(box, BorderLayout.SOUTH);
        return panel;
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
                createAndShowGUI();
            }
        });
    }
    public static void createAndShowGUI() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch(Exception e) {
            e.printStackTrace();
        }
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new Test2().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ColorProgressBar extends JProgressBar {
    private static final long serialVersionUID = -1265489165072929352L;

    private BlockedColorLayerUI colorUI = new BlockedColorLayerUI();
    public JLayer<JProgressBar> layer;
    private PropertyChangeSupport supporter = new PropertyChangeSupport(new WeakReference<ColorProgressBar>(this));

    public ColorProgressBar(BoundedRangeModel model) {
        super(model);
        layer = new JLayer<JProgressBar>(this, colorUI);
    }

    public Color getColor() {
        if (colorUI == null)
            return null;

        return colorUI.color;
    }

    public void setColor(Color color) {
        Color oldColor = colorUI.color;
        colorUI.color = color;
        supporter.firePropertyChange("color", oldColor, color);
    }

//     @Override
//     public void paintComponents(Graphics g) {
//         layer.paintComponents(g);
//     }

    class BlockedColorLayerUI extends LayerUI<JProgressBar> {
        public Color color = null;
        private BufferedImage bi;
        private int prevw = -1;
        private int prevh = -1;
        @Override public void paint(Graphics g, JComponent c) {
            if(color != null) {
                JLayer<?> jlayer = (JLayer<?>)c;
                JProgressBar progress = (JProgressBar)jlayer.getView();
                int w = progress.getSize().width;
                int h = progress.getSize().height;

                if(bi==null || w!=prevw || h!=prevh) {
                    bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
                }
                prevw = w;
                prevh = h;

                Graphics2D g2 = bi.createGraphics();
                super.paint(g2, c);
                g2.dispose();

                Image image = c.createImage(
                        new FilteredImageSource(bi.getSource(),
                                new ColorFilter(color)));
                g.drawImage(image, 0, 0, c);
            } else {
                super.paint(g, c);
            }
        }
    }
    class ColorFilter extends RGBImageFilter {
        Color color;

        public ColorFilter(Color color) {
            this.color = color;
        }

        @Override public int filterRGB(int x, int y, int argb) {
            int r = (int)((argb >> 16) & 0xff);
            int g = (int)((argb >>  8) & 0xff);
            int b = (int)((argb      ) & 0xff);
            return (argb & color.getRGB()) | (g<<16) | (r<<8) | (b);
        }
    }
}

【讨论】:

  • 有没有办法写,这样我就不用参考 .layer 字段了?我觉得即使我记录了该方法,也很有可能组织中的其他人可能会不正确地连接它,因为 Swing 或多或少是经过设计的,因此您自己添加 JComponents 而不是其中的字段。
猜你喜欢
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多