概要

透明にしたJFrameに半透明のデジタル時計を配置し、文字更新による背景色の再描画をテストします。

サンプルコード

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()));
    Container parent = SwingUtilities.getUnwrappedParent(label);
    if (parent != null && parent.isOpaque()) {
      repaintWindowAncestor(label);
    }
  }
});
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);
}
view all

解説

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

  • JFrame
    • 透明
      com.sun.awt.AWTUtilities.setWindowOpaque(frame, false); //JDK 1.6.0
      frame.setBackground(new Color(0x0, true)); //1.7.0
      
    • Window#setOpacity(...)(またはJDK 1.6.0AWTUtilities.setWindowOpacity(...))は、子コンポーネントを含めてすべて半透明になるので、このサンプルでは使用していない
  • JPanel
    • frame.getContentPane().add(panel)で追加
    • 半透明(二種類)
      • setOpaque(true)+半透明のアルファ成分をもつ色をsetBackground()で設定
      • JPanelsetOpaque(true)なので、ContentPaneから再描画しないと、JPanelに設定した半透明の背景色が重複して上書きされる(色が濃くなる)
      • setOpaque(false)+paintComponent()をオーバーライドして背景画像などを描画
  • JLabel
    • panel.add(label)で追加
    • 一秒ごとに文字列を変更する時計
    • setOpaque(false)で背景は透明

参考リンク

コメント

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