• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JFrameの透明化と再描画
#navi(../)
#tags(JFrame, Translucent, JPanel, JLabel, TexturePaint)
RIGHT:Posted by &author(aterai); at 2011-10-24
* JFrameの透明化と再描画 [#vb5228db]
半透明にした`JFrame`の再描画を行います。
---
category: swing
folder: TranslucentFrameRepaint
title: JFrameの透明化と再描画
tags: [JFrame, JRootPane, Translucent, JPanel, JLabel, TexturePaint, Clock]
author: aterai
pubdate: 2011-10-24T15:53:52+09:00
description: 透明にしたJFrameに半透明のデジタル時計を配置し、文字更新による背景色の再描画をテストします。
image: https://lh4.googleusercontent.com/-ujoDf8eD4vE/TqLcC0f2CHI/AAAAAAAABD4/LHaXXW6HW1k/s800/TranslucentFrameRepaint.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2014/02/translucent-jframe-repaint.html
    lang: en
---
* 概要 [#summary]
透明にした`JFrame`に半透明のデジタル時計を配置し、文字更新による背景色の再描画をテストします。

- &jnlp;
- &jar;
- &zip;
#download(https://lh4.googleusercontent.com/-ujoDf8eD4vE/TqLcC0f2CHI/AAAAAAAABD4/LHaXXW6HW1k/s800/TranslucentFrameRepaint.png)

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

** サンプルコード [#vc402d77]
* サンプルコード [#sourcecode]
#code(link){{
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()));
    if(label.getParent().isOpaque()) {
      repaintWindowAncestor(label);
    }
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
JLabel label = new JLabel(LocalTime.now().format(formatter), SwingConstants.CENTER);
Timer timer = new Timer(100, null);
timer.addActionListener(e -> {
  label.setText(LocalTime.now().format(formatter));
  Container parent = SwingUtilities.getUnwrappedParent(label);
  if (Objects.nonNull(parent) && parent.isOpaque()) {
    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();
// ...
private void repaintWindowAncestor(JComponent c) {
  JRootPane root = c.getRootPane();
  if (root == null) {
    return;
  }
  Rectangle r = SwingUtilities.convertRectangle(c, c.getBounds(), root);
  root.repaint(r.x, r.y, r.width, r.height);
}
//or
//private void repaintWindowAncestor(JComponent c) {
//  JRootPane root = c.getRootPane();
//    Rectangle r = c.getBounds();
//    r = SwingUtilities.convertRectangle(c, r, root);
//    root.repaint(r.x, r.y, r.width, r.height);
//  }
}}

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

- `JFrame`
-- 透明
#code{{
com.sun.awt.AWTUtilities.setWindowOpaque(frame, false);
//frame.setBackground(new Color(0,0,0,0)); //1.7.0
com.sun.awt.AWTUtilities.setWindowOpaque(frame, false); // JDK 1.6.0
frame.setBackground(new Color(0x0, true)); // JDK 1.7.0以降
}}
-- `AWTUtilities.setWindowOpacity(...)`、`Window#setOpacity(...)`は、子コンポーネントを含めてすべて半透明になるので、このサンプルでは使用していない
-- `Window#setOpacity(...)`(または`JDK 1.6.0`で`AWTUtilities.setWindowOpacity(...)`)は子コンポーネントを含めてすべて半透明になるので、このサンプルでは使用していない

- `JPanel`
-- `frame.getContentPane().add(panel)`で追加
-- 半透明(二種類)
--- `setOpaque(true)`+半透明のアルファ成分をもつ色を`setBackground()`で設定
--- `JPanel`が`setOpaque(true)`なので、`ContentPane`から再描画しないと、`JPanel`に設定した半透明の背景色が重複して上書きされる(色が濃くなる)
--- `JPanel`が`setOpaque(true)`なので`ContentPane`から再描画しないと`JPanel`に設定した半透明の背景色が重複して上書きされる(色が濃くなる)
--- `setOpaque(false)`+`paintComponent()`をオーバーライドして背景画像などを描画

- `JLabel`
-- `panel.add(label)`で追加
-- 一秒ごとに文字列を変更する時計
-- `setOpaque(false)`で背景は透明

** 参考リンク [#s8b81bf4]
* 参考リンク [#reference]
- [http://www.viva-edo.com/komon/edokomon.html 江戸の文様(和風素材・デスクトップ壁紙)]
- [http://www.yourname.jp/soft/digitalfonts-20090306.shtml ユアネーム・7セグ・12セグフォント大全集]
- %%[http://www.yourname.jp/soft/digitalfonts-20090306.shtml ユアネーム・7セグ・12セグフォント大全集]%%

** コメント [#q7c95e31]
- フォントをデジタル時計ぽいものに変更。 -- [[aterai]] &new{2012-02-10 (金) 17:35:12};
-- スクリーンショットは入れ替えるのが面倒なので、古いフォントのまま。 -- [[aterai]] &new{2012-04-17 (火) 17:26:14};
* コメント [#comment]
#comment
- フォントをデジタル時計ぽいものに変更。 -- &user(aterai); &new{2012-02-10 (金) 17:35:12};
-- スクリーンショットは入れ替えるのが面倒なので、古いフォントのまま。 -- &user(aterai); &new{2012-04-17 (火) 17:26:14};

#comment