下記の質問に関連するのですが。
たぶんアルゴリズムの問題。画像の不透明度を上げながらフェードイン(?)したいんですが。(30013)|teratail
https://teratail.com/questions/30013
MemoryImageSource
って、今回のケースだとすべてのピクセルに透明度を設定するので効率が悪いような気がします。
「50x50の水色の矩形の画像を用意」で回答されているもの近い方法の、AlphaComposite
で透明度を変える処理の例を示します。
lang
1 import java.awt.*;
2 import java.awt.event.*;
3 import java.util.concurrent.Executors;
4 import javax.swing.*;
5
6 final class MyPanel extends JPanel {
7
8 JFrame frame;
9 Image img;
10 volatile float alpha;
11 int imageWidth = 145; // TODO 画像に合わせて変える
12 int imageHeight = 157; // TODO 画像に合わせて変える
13
14 MyPanel(JFrame f) {
15 this.frame = f;
16 this.img = new ImageIcon("img.png").getImage();
17 this.alpha = 0.0f;
18 }
19
20 @Override
21 protected void paintComponent(Graphics g) {
22 Graphics2D g2 = (Graphics2D)g;
23 System.out.println("alpha=" + alpha);
24 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
25 g2.drawImage(img, 0, 0, imageWidth, imageHeight, this);
26 }
27
28 void fadeIn() {
29 Executors.newSingleThreadExecutor().execute(new Runnable() {
30 public void run() {
31 while (alpha < 1.0f) {
32 float f = alpha + 0.03f;
33 if (f > 1.0f) {
34 alpha = 1.0f;
35 break;
36 }
37 alpha = f;
38 frame.repaint();
39 sleep(50L);
40 }
41 }
42 });
43 }
44
45 void fadeOut() {
46 Executors.newSingleThreadExecutor().execute(new Runnable() {
47 public void run() {
48 while (alpha >= 0.0f) {
49 float f = alpha - 0.03f;
50 if (f < 0.0f) {
51 alpha = 0.0f;
52 break;
53 }
54 alpha = f;
55 frame.repaint();
56 sleep(50L);
57 }
58 }
59 });
60 }
61
62 static void sleep(long millis) {
63 try {
64 Thread.sleep(millis);
65 } catch (InterruptedException e) {
66 throw new RuntimeException(e);
67 }
68 }
69
70 }
71
72 public final class App {
73
74 public static void main(String[] args) {
75 EventQueue.invokeLater(new Runnable() {
76 public void run() {
77 JFrame f = new JFrame("test");
78 f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
79 f.setSize(600, 400);
80 f.setLocationRelativeTo(null);
81 JPanel p = new JPanel();
82 MyPanel canvas = new MyPanel(f);
83 JButton fadeOutButton = new JButton("fade out");
84 fadeOutButton.addActionListener(new ActionListener() {
85 @Override
86 public void actionPerformed(ActionEvent e) {
87 canvas.fadeOut();
88 }
89 });
90 JButton fadeInButton = new JButton("fade in");
91 fadeInButton.addActionListener(new ActionListener() {
92 @Override
93 public void actionPerformed(ActionEvent e) {
94 canvas.fadeIn();
95 }
96 });
97 p.add(fadeInButton);
98 p.add(fadeOutButton);
99 f.add(canvas, BorderLayout.CENTER);
100 f.add(p, BorderLayout.NORTH);
101 f.setVisible(true);
102 }
103 });
104 }
105
106 }
排他制御する箇所は省略しているため、どちらかの処理が動いているときにもう片方の処理を動かすとおかしなことになりますのでご注意ください。
それと、ここはあまり自信が無いのですが、透明化に限らず、Java2Dの機能で画像の加工処理・フィルター処理などを使う場合、描画するパネルだけをrepaint
するとおかしな挙動になることがあります。
そのため、今回の例ではフレームごと再描画させるようにしています。
参考リンク:
Crossfadeで画像の切り替え - Java Swing Tips
http://ateraimemo.com/Swing/Crossfade.html