protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
g2.drawString("俺に任せろー!バリバリー!",0,20);
}
これを実行すると、このパネルに載せたボタンも透明になってしまいます。
しかし、Swingの機能で一番上にあるコンポーネントのみを再描画するため、二回目以降の描画では半透明にならず見た目正しく描画されてしまいました。
さて、これを正してみませう。
1.コンポーネントを半透明にする。
これが一番簡単な方法です。
JButton b = new JButton("test1"); b.setOpaque(false);
単純な考えで、透明だったら下から描画しなきゃいけないだろうと言う事です。これで簡単に親要素をダーティーリジョンに登録できます。ただ、これでうまくいかない場合があります。
コンポーネントの中に不透明なコンポーネントがある。しかも外からいじれない時です。
さて、これを何とか是正してみましょう。方法は2通りぐらいあります。
1repaint要求を自分で変更する
2RepaintManagerを作成する。
1も1も考え方は同じで、再描画される前に描画対象を変更してしまいます。
1は載せる物全部に対して自分で再描画時の対象変更を書かないといけないから部品がいっぱいあると論外。また、privateで外から弄ることの出来ない不透明コンポーネントに対しては結局変更できないパネェ欠点がある。
2はすっきりしてるし、簡単だし、外から変更できないコンポーネントにも有効だけど、RepaintManagerは全体で一つしか使えないというパネェ欠点がある。
パーツが少なくて、かつ、不透明コンポーネントは全て外から変更できる場合は1を選んだ方が他の場所でもRepaintManagerを変更したいときとかに問題が起こりません。
が、上記の条件を一つでも満たさない限りは?を選ぶしかありません。
さて、1,2共通して行っておくことがあります。
今回JButtonを載せるパネルはTestというJPanelを拡張したクラスになっていますが、これに以下の関数を追加します。
public void paint(Graphics g){
paintComponent(g);
paintComponents(g);
}
さて、1の方から見ていきます。
Testに追加するJButtonを以下の様に書き換えます。
JButton b = new JButton("test1"){
Test parent=Test.this;
この様にrepaintを呼ばれると、parentのrepaintが呼ばれる様に変更してしまいます。Test parent=Test.this;
public void repaint(long tm, int x, int y, int w, int h) {
if(parent == null){
super.repaint(tm,x,y,w,h);
return;
}
Point p = SwingUtilities.convertPoint(this,x,y,parent);
parent.repaint(tm,p.x,p.y,w,h);
}
};
次に2のRepaintManagerを使った方法。
RepaintManagerは描画される前に処理を横取りして描画対象を変更することが出来ます。
便利なのですが、全体で1つしか使えないのが使いにくい。
以下、RepaintManagerを使った全ソースコード。
import java.awt.AlphaComposite;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
public class Test extends JPanel implements Runnable{
Test(){
setLayout(new FlowLayout());
JButton b = new JButton("test1");
add(b);
RepaintManager.setCurrentManager(new RepaintManager2());
}
class RepaintManager2 extends RepaintManager{
public void addDirtyRegion(JComponent c, int x, int y, int w,int h) {
Container parent=c.getParent();
while(parent!=null){
if(!parent.isVisible())return;
if(parent instanceof Test){
Point p = SwingUtilities.convertPoint(c,x,y,parent);
x = p.x;
y = p.y;
c = (JComponent)parent;
//Testは複数あるかも知れないからbreakはしません
}
parent = parent.getParent();
}
super.addDirtyRegion(c,x,y,w,h);
}
}
public void paint(Graphics g) {
paintComponent(g);
paintComponents(g);
}
public Dimension getPreferredSize() {
Dimension k =super.getPreferredSize();
k.width += 30;
return k;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
g2.drawString("俺に任せろー!バリバリー!",0,20);
}
public void run(){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Test());
}
}
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
public class Test extends JPanel implements Runnable{
Test(){
setLayout(new FlowLayout());
JButton b = new JButton("test1");
add(b);
RepaintManager.setCurrentManager(new RepaintManager2());
}
class RepaintManager2 extends RepaintManager{
public void addDirtyRegion(JComponent c, int x, int y, int w,int h) {
Container parent=c.getParent();
while(parent!=null){
if(!parent.isVisible())return;
if(parent instanceof Test){
Point p = SwingUtilities.convertPoint(c,x,y,parent);
x = p.x;
y = p.y;
c = (JComponent)parent;
//Testは複数あるかも知れないからbreakはしません
}
parent = parent.getParent();
}
super.addDirtyRegion(c,x,y,w,h);
}
}
public void paint(Graphics g) {
paintComponent(g);
paintComponents(g);
}
public Dimension getPreferredSize() {
Dimension k =super.getPreferredSize();
k.width += 30;
return k;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
g2.drawString("俺に任せろー!バリバリー!",0,20);
}
public void run(){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Test());
}
}