TITLE:JFrameの透明化と再描画
#navi(../)
RIGHT:Posted by [[aterai]] at 2011-10-24
*JFrameの透明化と再描画 [#vb5228db]
半透明にしたJFrameの再描画を行います。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(https://lh4.googleusercontent.com/-ujoDf8eD4vE/TqLcC0f2CHI/AAAAAAAABD4/LHaXXW6HW1k/s800/TranslucentFrameRepaint.png)

**サンプルコード [#vc402d77]
#code{{
private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
private final JLabel label = new JLabel(df.format(new Date()));
private final Timer timer = new Timer(1000, new ActionListener() {
  @Override public void actionPerformed(ActionEvent e) {
    label.setText(df.format(new Date()));
    repaintWindowAncestor(label);
  }
});
private void repaintWindowAncestor(Component c) {
  Window w = SwingUtilities.getWindowAncestor(c);
  if(w instanceof JFrame) {
    JFrame f = (JFrame)w;
    JComponent cp = (JComponent)f.getContentPane();
    //cp.repaint();
    Rectangle r = c.getBounds();
    r = SwingUtilities.convertRectangle(c, r, cp);
    cp.repaint(r.x, r.y, r.width, r.height);
    //r = SwingUtilities.convertRectangle(c, r, f);
    //f.repaint(r.x, r.y, r.width, r.height);
  }else{
    c.repaint();
  }
}
}}

**解説 [#k3a01a3f]
上記のサンプルでは、実際はJFrameが半透明ではなく、以下のように%%半透明にした%%透明にしたJFrameに、半透明のJPanelを追加、さらにその子として一秒ごとに文字列が変化するJLabel(時計)を配置しています。

-JFrame
--透明
#code{{
com.sun.awt.AWTUtilities.setWindowOpaque(frame, false);
//frame.setBackground(new Color(0,0,0,0)); //1.7.0
}}
--AWTUtilities.setWindowOpacity(...)、Window#setOpacity(...)は子コンポーネント全体が半透明になるので、このサンプルでは使用していない
-JPanel
--frame.getContentPane().add(panel)で追加
--半透明(二種類)
---setOpaque(true)+半透明のアルファ成分をもつ色をsetBackground()で設定
---setOpaque(false)+paintComponent()をオーバーライドして背景画像などを描画
-JLabel
--panel.add(label)で追加
--一秒ごとに文字列を変更する時計
--setOpaque(false)で透明

%%JFrameが半透明なので%%、JFrame自体は透明ですが、そのContentPaneから再描画しないと、JLabelとの間にあるContainerの背景色などが重複して上書きされる(色が濃くなる)ようです。

**参考リンク [#s8b81bf4]
-[http://www.viva-edo.com/komon/edokomon.html 江戸の文様(和風素材・デスクトップ壁紙)]

**コメント [#q7c95e31]
#comment