Swing/TranslucentFrameRepaint のバックアップの現在との差分(No.5)
TITLE:JFrameの透明化と再描画
Posted by aterai at 2011-10-24
JFrameの透明化と再描画
半透明にした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:
hreflang:
href: https://java-swing-tips.blogspot.com/2014/02/translucent-jframe-repaint.html lang: en
概要
透明にしたJFrame
に半透明のデジタル時計を配置し、文字更新による背景色の再描画をテストします。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spandel
private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
#spanend
#spandel
private final JLabel label = new JLabel(df.format(new Date()));
#spanend
#spandel
private final Timer timer = new Timer(1000, new ActionListener() {
#spanend
@Override public void actionPerformed(ActionEvent e) {
label.setText(df.format(new Date()));
if(label.getParent().isOpaque()) {
repaintWindowAncestor(label);
}
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
#spanadd
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
#spanend
#spanadd
JLabel label = new JLabel(LocalTime.now().format(formatter), SwingConstants.CENTER);
#spanend
#spanadd
Timer timer = new Timer(100, null);
#spanend
#spanadd
timer.addActionListener(e -> {
#spanend
label.setText(LocalTime.now().format(formatter));
Container parent = SwingUtilities.getUnwrappedParent(label);
if (Objects.nonNull(parent) && parent.isOpaque()) {
repaintWindowAncestor(label);
}
});
#spandel
private void repaintWindowAncestor(Component c) {
#spanend
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();
#spanadd
// ...
#spanend
#spanadd
private void repaintWindowAncestor(JComponent c) {
#spanend
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);
}
解説
上記のサンプルでは、実際はJFrameが半透明ではなく、以下のように解説
上記のサンプルでは、実際はJFrame
が半透明ではなく、以下のように透明にしたJFrame
に半透明のJPanel
を追加、さらにその子として一秒ごとに文字列が変化するJLabel
(時計)を配置しています。
JFrame
- 透明
-
JFrame
- 透明
#spandel com.sun.awt.AWTUtilities.setWindowOpaque(frame, false); #spanend #spandel //frame.setBackground(new Color(0,0,0,0)); //1.7.0 #spanend #spanadd com.sun.awt.AWTUtilities.setWindowOpaque(frame, false); // JDK 1.6.0 #spanend #spanadd frame.setBackground(new Color(0x0, true)); // JDK 1.7.0以降 #spanend
- 透明
- AWTUtilities.setWindowOpacity(...)、Window#setOpacity(...)は子コンポーネント全体が半透明になるので、このサンプルでは使用していない
-
Window#setOpacity(...)
(またはJDK 1.6.0
でAWTUtilities.setWindowOpacity(...)
)は子コンポーネントを含めてすべて半透明になるので、このサンプルでは使用していない
-
- frame.getContentPane().add(panel)で追加
- 半透明(二種類)
- setOpaque(true)+半透明のアルファ成分をもつ色をsetBackground()で設定
- JPanelがsetOpaque(true)なので、ContentPaneから再描画しないと、JPanelに設定した半透明の背景色が重複して上書きされる(色が濃くなる)
- setOpaque(false)+paintComponent()をオーバーライドして背景画像などを描画
- setOpaque(true)+半透明のアルファ成分をもつ色をsetBackground()で設定
-
JPanel
-
frame.getContentPane().add(panel)
で追加 - 半透明(二種類)
-
setOpaque(true)
+半透明のアルファ成分をもつ色をsetBackground()
で設定 -
JPanel
がsetOpaque(true)
なのでContentPane
から再描画しないとJPanel
に設定した半透明の背景色が重複して上書きされる(色が濃くなる) -
setOpaque(false)
+paintComponent()
をオーバーライドして背景画像などを描画
-
-
- panel.add(label)で追加
- 一秒ごとに文字列を変更する時計
- setOpaque(false)で背景は透明
-
JLabel
-
panel.add(label)
で追加 - 一秒ごとに文字列を変更する時計
-
setOpaque(false)
で背景は透明
-
参考リンク
参考リンク
コメント
- フォントをデジタル時計ぽいものに変更。 -- aterai
コメント
- フォントをデジタル時計ぽいものに変更。 -- aterai
- スクリーンショットは入れ替えるのが面倒なので、古いフォントのまま。 -- aterai