TITLE:JLayerを使ってJProgressBarの色相を変更する
#navi(../)
#tags(JProgressBar, JLayer, RGBImageFilter, SwingWorker)
RIGHT:Posted by &author(aterai); at 2013-06-24
* JLayerを使ってJProgressBarの色相を変更する [#d3b2b8a6]
`JLayer`を使って`JProgressBar`の色相を緑から赤に変更します。

#download
#ref(https://lh3.googleusercontent.com/-BOomq0cC-U4/UceBZ2TsWWI/AAAAAAAABug/yoXs3wbBVGk/s800/ColorChannelSwapFilter.png)

** サンプルコード [#x5a13e52]
#code(link){{
class BlockedColorLayerUI extends LayerUI<JProgressBar>{
  public boolean isPreventing = false;
  private BufferedImage bi;
  private int prevw = -1;
  private int prevh = -1;
  @Override public void paint(Graphics g, JComponent c) {
    if(isPreventing) {
      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 RedGreenChannelSwapFilter()));
      g.drawImage(image, 0, 0, c);
    }else{
      super.paint(g, c);
    }
  }
}

class RedGreenChannelSwapFilter extends RGBImageFilter{
  @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 & 0xff000000) | (g<<16) | (r<<8) | (b);
  }
}
}}

** 解説 [#u70c6460]
- `setStringPainted(true)`: 上
-- `JProgressBar#setStringPainted(true)`を設定
- `setStringPainted(true)`: 下
-- `JProgressBar#setStringPainted(true)`を設定
-- チェックボックスがチェックされると、`JProgressBar#setForeground(Color)`で色が変更
- `setStringPainted(false)`: 上
-- デフォルトの`JProgressBar`
- `setStringPainted(false)`: 上
-- チェックボックスがチェックされると、`JLayer`を使って色を変更
--- `Windows 7`での中断状態風に、緑を赤に入れ替えるため、`RGBImageFilter#filterRGB(...)`をオーバーライド

** 参考リンク [#wfd4e65e]
- [[RGBImageFilterでアイコンの色調を変更>Swing/RatingLabel]]
- [[JProgressBarの文字列をJLayerを使って表示する>Swing/ProgressStringLayer]]

** コメント [#bd6a9d2c]
- `NimbusLookAndFeel`の場合、`JProgressBar#setOpaque(true)`として`JLayer`と`RedGreenChannelSwapFilter`を使用しないと、フチが半透明にならない。また`NimbusLookAndFeel`の場合、`JProgressBar#setForeground(Color)`で変化するのは他の`LookAndFeel`とは異なり、進捗文字列になる。 -- [[aterai]] &new{2013-06-25 (火) 20:51:09};

#comment