最初に作った課題はボタンがあり、クリックすると楕円を描きました。これは一度見えなくなったウインドウが戻ることなどで絵が消えてしまった時に描き直して、どんな時に消えるのかいろいろ試してみるためでした。
描画メソッドをpaintComponentに書くことでウインドウが戻ったときに絵も戻るようになりました。
しかし、これでもクリックなどで絵が変化する場合はこれで満足できるわけではないということを示したいと思います。
ボタンをクリックするとランダムに円をたくさん描くプログラムを作ります。
これはクリックする度に円を新しく描き直します。また、ウインドウが戻ったときにも円を新しく描き直します。
図中、左上の数字は左がpaintComponent()内を実行した回数。右がクリックした回数です。
import java.awt.*; import javax.swing.*; import java.awt.event.*; public class EventRandom extends JFrame implements ActionListener{ JButton mybtn; MyPanel mypnl; int pcct=0; //paintComponentが呼び出された回数 int clct=0; //クリックした回数 public EventRandom() { setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(400,300); setTitle("イベントで変化する模様"); mypnl = new MyPanel(); mypnl.setSize(400,300); mypnl.setBackground(new Color(255,255,191)); mybtn = new JButton("draw"); setLayout(new BorderLayout()); add(mypnl, BorderLayout.CENTER); add(mybtn,BorderLayout.SOUTH); mybtn.addActionListener(this); setVisible(true); } public void actionPerformed(ActionEvent e) { if (e.getSource() == mybtn) { clct++; mypnl.repaint(); } } public static void main(String[] args){ EventRandom myframe = new EventRandom(); } public class MyPanel extends JPanel{ int w=30; //楕円の幅 int h=20; //楕円の高さ Color c = new Color(0,0,0); //楕円の色 int dc = 51; //色の変化の大きさ int dx = 50; //横位置の変化の大きさ public void paintComponent(Graphics myg){ super.paintComponent(myg); pcct++; for(int i=0; 10>i; i++){ nextColor(); myg.setColor(c); int x = (int)(400*Math.random()); int y = (int)(300*Math.random()); int h = (int)(50*Math.random()+5); myg.fillOval(x-h/2,y-h/2,h,h); } myg.clearRect(10,4,60,20); myg.setColor(Color.black); myg.drawString(pcct+" "+clct,10,20); } public void nextColor(){ int r=c.getRed(); int g=c.getGreen(); int b=c.getBlue(); g = (int)(g + dc*Math.random()); if (g > 255){ g = 0; } c = new Color(r,g,b); } } }
ポイントはpaintComponentメソッドを直接呼び出さずに、repaint()メソッドを使うことです。
actionPerformedの中に、mypnl.repaint()とあります。これでMyPanelクラスのインスタンスであるmypnlの中のpaintComponentメソッドを呼び出すことになります。clct++はクリック回数を数えているところです。
paintComponentメソッドにはpcct++があり、これで呼び出された回数を数えています。
paintComponentメソッドの最後の3行は文字部分の背景をクリアしてその数を書いています。
クリックする度にクリアせず、次の様に書き足していくようにはならないでしょうか。
実はpaintComponentのすぐ後に書かれているsuper.paintComponent(myg)をコメントアウト(コメントにして実行しない様にすること)をすると上記の様になります。
public void paintComponent(Graphics myg){ //super.paintComponent(myg); pcct++; for(int i=0; 10>i; i++){
superはここではMyPanelの親クラスであるJPanelのことで、そのpaintComponentの内容を先に実行するということです。
super.paintComponentをしないというのはお薦めできませんが、それでもウインドウを最小化して戻すなどして書き直されると描きためた円はなくなってしまいます。
ウインドウの大きさを変える場合も同様になります。
上記プログラムをつくって動作を確認しなさい。