- PR -

画面のちらつき

1
投稿者投稿内容
yasshi
会議室デビュー日: 2006/09/25
投稿数: 9
投稿日時: 2007-08-07 15:29
Timerクラス(Timer以外でもいいのですが)を使って刻々と変化するプログラムを作りたいのですが画面がちらついて困っています。
ダブルバッファリングはしているので、timerのactionListenerの中でrepaint()を呼び出してるのが問題だとは思うのですが、その解決方法がわからず困っています。どのように実装すればいいのでしょうか?
描画の内容はありませんが、とりあえずこんな感じのソースです。よろしくお願いします。

public class Test extends JFrame{

Container cont = getContentPane();

JMenuBar menu_bar = new JMenuBar();

Image off_image = null;
Graphics off_g = null;


Timer timer;


public static void main(String args[]){

Test window = new Test();

window.setSize(1024,768);

window.addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
);

window.setVisible(true);
}

public Test(){

super("てすと");

setResizable(false);

setVisible(false);

setBackground(Color.gray.brighter());

setLocation(300,100);

//メニュー設定

JMenu menu1 = new JMenu("設定");

JMenuItem menu1_item1 = new JMenuItem("設定1");
menu1_item1.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){

}
}
);

menu1.add(menu1_item1);
menu_bar.add(menu1);

cont.add(menu_bar,"North");

timer = new Timer(1,
new ActionListener(){
public void actionPerformed(ActionEvent e){
repaint();
}
}
);

timer.start();

}



public void update(Graphics g){
paint(g);
}

public void paint(Graphics g){

super.paint(g);

int width = getSize().width - getInsets().left - getInsets().right ;
int height = getSize().height - getInsets().top - getInsets().bottom - menu_bar.getHeight();

if(off_image==null){

off_image = createImage(getSize().width,getSize().height);
off_g = off_image.getGraphics();

}
g.setClip(getInsets().left, getInsets().top + menu_bar.getHeight(),
width ,
height);

g.drawImage(off_image,0,0,this);
}


}

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-08-07 17:11
JFrameではなく、JPanelを継承してクラスを作りましょう。

ちらつきの原因はsuper.paint(g);でクリアしてから
独自のペイントを行っているからなのですが、
super.paint(g);を呼ばないとフレームの外枠の表示がうまくいきません。
yasshi
会議室デビュー日: 2006/09/25
投稿数: 9
投稿日時: 2007-08-07 22:45
教えていただいたようにJPanelをつかってやるとちらつきが無くなりました。
ありがとうございました。
yasshi
会議室デビュー日: 2006/09/25
投稿数: 9
投稿日時: 2007-08-08 18:08
またまたすみません。
作ったプラグラムはWindowsでは問題なく動いていたのですが、試しにMacで実行してみると、ちらつきは無いのですが、メニューが表示されなくなってしまいます。
メニューの部分を一度クリックするとその後は表示されるようになるのですが初期状態では消えています。
解決策はあるでしょうか?
修正したプログラムは下のような感じです。

あともう一つ質問なんですが、描画した上や、画像の上にテキストフィールドなどを重ねて表示することは、可能でしょうか? 可能ならどのようにすればいいのでしょうか?
よろしくお願いします。

public class Test extends JFrame{

Container cont = getContentPane();

JMenuBar menu_bar = new JMenuBar();

Image off_image = null;
Graphics off_g = null;
TestPanel testPanel;

Timer timer;


public static void main(String args[]){

Test window = new Test();

window.setSize(800,500);

window.addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
);

window.setVisible(true);
}

public Test(){

super("てすと");

setResizable(false);

setVisible(false);

setBackground(Color.gray.brighter());

setLocation(300,100);

//メニュー設定

JMenu menu1 = new JMenu("設定");

JMenuItem menu1_item1 = new JMenuItem("設定1");
menu1_item1.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){

}
}
);

menu1.add(menu1_item1);
menu_bar.add(menu1);

cont.add(menu_bar,"North");

testPanel = new TestPanel();
cont.add(testPanel);


}


public class TestPanel extends JPanel{

int i =0;
TestPanel(){

timer = new Timer(1,
new ActionListener(){
public void actionPerformed(ActionEvent e){
i++;
repaint();
}
}
);

timer.start();
}


public void paint(Graphics g){

super.paint(g);

int width = getSize().width - getInsets().left - getInsets().right ;
int height = getSize().height - getInsets().top - getInsets().bottom ;


off_image = createImage(getSize().width,getSize().height);
off_g = off_image.getGraphics();


g.setClip(0, 0,
width ,
height);

off_g.drawRect(0,0,i,i);
g.drawImage(off_image,0,0,this);

}

public void update(Graphics g){
paint(g);
}

}

}
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-08-08 18:54
ソースコードの掲示にはBBコードのcodeタグを使ってください。
見やすくなりますよ。

私はMacを持っていないのでなんとも言えませんが、
setVisible()をイベントディスパッチスレッドで実行すれば
描画されるかもしれませんね。

即物的な対応なら、メニューが初期に表示されない、しかし、描画要求があれば
表示されるのだとしたらどこかでrepaint()すると表示されるのでは?

他のコンポーネントを重ねたいとのことですが、可能です。
提示のソースではpaint()をオーバーライドしているようですが、
paintComponent()をオーバーライドするようにしてみてください。

JPanelではpaintChildren()で子コンポーネントを描画しています。
paint()のデフォルトの実装ではpaintComponent()で本体を、
paintBorder()でコンポーネントのボーダーを、paintChildren()で
子コンポーネントを描画しています。
これを阻害しないようにすればちゃんと描画されるはずです。
yasshi
会議室デビュー日: 2006/09/25
投稿数: 9
投稿日時: 2007-08-08 23:59
引用:
ソースコードの掲示にはBBコードのcodeタグを使ってください。


次回からそうします。


paintComponent()をオーバーライトしてということはpaint()をpaintComponent()にして、TestPanel()コンテキストの中でテキストフィールドなんかを実装して、そのパネルをフレームで呼び出しaddするという感じでいいのでしょうか?

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-08-09 09:53
引用:

yasshiさんの書き込み (2007-08-08 23:59) より:
paintComponent()をオーバーライトしてということはpaint()をpaintComponent()にして、TestPanel()コンテキストの中でテキストフィールドなんかを実装して、そのパネルをフレームで呼び出しaddするという感じでいいのでしょうか?



ややこしいですね
国語の話ではありませんが、文は適度に細かく分けた方が誤解のない文にできますよ。

1. 現在のTestPanelクラスのpaint()の処理をpaintComponent()に移動
2. TestPanelにJTextFieldなど表示したいコンポーネントをadd()する
3. JFrame#getContentPane()に対してTestPanelをadd()する

といったところでしょうか。
1

スキルアップ/キャリアアップ(JOB@IT)