TITLE:JFrameの透明化と再描画

Posted by at 2011-10-24

JFrameの透明化と再描画

半透明にした`JFrame`の再描画を行います。

  • &jnlp;
  • &jar;
  • &zip;
TranslucentFrameRepaint.png

サンプルコード

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);
    }
  }
});
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();
  }
}
View in GitHub: Java, Kotlin

解説

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

  • `JFrame`
    • 透明
      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()`で設定
      • `JPanelsetOpaque(true)なので、ContentPaneから再描画しないと、JPanel`に設定した半透明の背景色が重複して上書きされる(色が濃くなる)
      • `setOpaque(false)+paintComponent()`をオーバーライドして背景画像などを描画
  • `JLabel`
    • `panel.add(label)`で追加
    • 一秒ごとに文字列を変更する時計
    • `setOpaque(false)`で背景は透明

参考リンク

コメント

  • フォントをデジタル時計ぽいものに変更。 -- aterai
    • スクリーンショットは入れ替えるのが面倒なので、古いフォントのまま。 -- aterai