プロが教える店舗&オフィスのセキュリティ対策術

 paint( )メッソドをオーバーロードについて

 今晩は、JAVA初心者です、宜しくお願いします。

 paint( )メッソドをオーバーロードする時に、<< A >>のコードはそのまま、
 g.drawStringを書いていますが、<< B >>のコードでは、
 super.paint( )で親クラスを呼んでやらないと、エラーになります。

 この両者の違いが全く理解出来ません、どこがどのように違うのでしょうか。
 宜しくお願い致します。

========================================
<< A >>

public class Sample extends Applet
{
public void paint(Graphics g)
{
g.drawString("Applet",50,50);
}
}

=======================================
<< B >>

public class JFrame_Test extends JFrame
{
JFrame_Test()
{
setSize(400,300);
setTitle("JFrame_Test");
}

public void paint(Graphics g)
{
super.paint(g);
g.drawString("Today",70,70);
}

public static void main(String[] args)
{
JFrame jf = new JFrame_Test();
jf.setVisible(true);
}
}

========================================

A 回答 (10件)

「<< B >>のコードでは、super.paint( )で親クラスを呼んでやらないと、エラーになります。


とのことですが, 具体的にはどのようなエラーになるんでしょうか?
    • good
    • 0
この回答へのお礼

Tacosanさん、回答有難うございます。

super.paint( )をコメントアウトすると、フレームが透明になって表示され、
下側にある画像等の文字が透けて見えます。

お礼日時:2010/10/04 09:54

その質問は、先の回答3での復習のコードや、今までがわからないと理解できないと思いますが、大丈夫でしょうか?



今までのやりとりは、これを理解するための説明のつもりです。


一応説明しておくと、本来swingでpaintメソッドをオーバーライドしてしまうと、正しく表示されません。
しかしケース2では、paintメソッドの中で、super.paintを実行しています。
これは、継承元のpaintを実行させるものです。
つまり、この1行のために、paintメソッドをオーバーライドしていないのと同じことになります。

paintメソッドの実行後にdrawStringを実行しているため、一見正常な動作にみえます。

ただし、今回はたまたまであり、うまくいかない場合もありますので、ちゃんとpaintComponentで処理しなければなりません。
    • good
    • 0
この回答へのお礼

ngsvxさん、回答有難うございました。

今後とも宜しくお願いします。

お礼日時:2010/10/18 21:59

●回答7


>g.drawString("ABC",100,100);を書く場所は、Awtなら、 paint(Graphics g);内、
>Swingなら、paintComponentメソッド内というルールはないのでしょうか。

そういうルールです。


●回答8
>また、Awt、Swingクラスのコードをどのようにしたら見ることが出来るのでしょうか。
ソースを見ても、余計に観覧するだけだと思います。
swingは多機能なため、コードが非常に複雑です。
かなり上級者にならないと難しいと思います。
どうしても見たいのであれば、jdkのフォルダーにあるsrc.zipにソースコードがあります。
    • good
    • 0
この回答へのお礼

 ngsvxさん、何度も丁重な回答有難うございます。

 >g.drawString("ABC",100,100);を書く場所は、Awtなら、 paint(Graphics g);内、
 >Swingなら、paintComponentメソッド内というルールはないのでしょうか。

 上の質問について再度質問いたします。
 【case 2】のコードでは、Swingでありながら、paint();メソッドの中に書かれていて
正常に動作します。
 これはどのような仕組みで動作しているのでしょうか。
 また、paintComponent();との関係はどのように考えるべきなのでしょうか。

 宜しくお願い致します。


========================================================
【case 1】
    
class JFrameTest1 extends JFrame
{
public static void main(String[] args)
{
myJPanel panel = new myJPanel();
JFrameTest1 mp = new JFrameTest1();

mp.add(panel);
mp.setVisible(true);
}
}

class myJPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.fillRect(50,50,100,100);
}
}
============================================================
【case 2】

public class JFrameTest2 extends JFrame
{
public void paint(Graphics g)
{
super.paint(g);
g.drawString("ABC",100,100);
}

public static void main(String[] args)
{
JFrameTest2 jf = new JFrameTest2();
jf.setVisible(true);
}
}
============================================================

お礼日時:2010/10/11 21:56

●回答1


>・ ユーザーがSwingクラスを継承した子クラスで描画処理を行う場合には、親クラス
> (Swingクラス?)のpaintComponent();を呼び出し、その中にユーザーの設計する描画
> メソッドをオーバーライドして定義する。

「呼び出し」というのがわかりませんが、

親クラスのメソッドであるpaintComponent()をオーバーライドし、その中にユーザーの
設計する描画処理を記述する

ということでしたらOKです。


●回答2
>と書いた場合には、親クラスSwingのpaint();メソッド内にある、paintComponent以外の
>メソッド(paintBorder、paintChildren)は、当然呼び出されないという考えでよいのですか。

paint()メソッドはオーバーライドされておらず、そのままですので

public void paint(Graphics g){

 paintBackground(g);
 paintComponent(g);
 paintChildren(g);
 paintBorder(g);

}

は実行されます。
したがって、paintBorder,paintChildrenなども実行されます。


●回答3
>・ super.paint(g);は、親クラスのpaint()内の全てのメソッドをオーバーライドしますが、

これは、勘違いをしているか、用語の使い方が間違っているかだと思います。

super.paint(g);は、親クラスのpaint()内の全てのメソッドをオーバーライド「しません」。

もしかしたら、継承/オーバーライドの仕組みについて理解が不足していませんでしょうか?

簡単に復習しましょう。確認してください。

class AAA
{
 public void show(){
  System.out.println("AAA-show()");
 }

 public void method(){
  show();
 }

}

class BBB1
  extends AAA
{
 public void show(){
  System.out.println("BBB1-show()");
 }

 static public void main(String[] arg){
  BBB1 app = new BBB1();
  app.method();
 }

}

class BBB2
  extends AAA
{
 public void show(){
  super.show();
  System.out.println("BBB2-show()");
 }

 static public void main(String[] arg){
  BBB2 app = new BBB2();
  app.method();
 }

}

以上のコードで、
BBB1、BBB2それぞれのmainを実行した場合どうなるかわかりますか?

BBB1の実行結果
----
BBB1-show()
----

BBB2の実行結果
----
AAA-show()
BBB2-show()
----

オーバーライドというのは、継承したときに継承元のクラスのメソッドを再定義することで
処理を「差し替える」ことです。


●回答4
>親クラスのpaint(g);内に定義されている全てのメソッドは、何個有るのでしょうか。
知りません。というか、知ることに意味はありません。
大事なのは、
・独自の描画をするときにはpaintComponentをオーバーライドするということ、
・今回説明している、全体的な仕組みを理解すること
です。

ちなみに、先に私が書いたpaintBackgroundというのは実際には存在しません。
おそらく、メソッドの中に直接記述しているのではないかと思います。

●回答5
>また、public void setBorder(Border border){}と、paintBorder(g);との使い分け
>みたいなものはあるのでしょうか。)

setBorderは描画するボーダーの種類を設定するだけで、実際には描画しません。
実際の描画はpaintBorderで行っているます。


●回答6
>g.drawString("ABC",100,100);は、Swing内のpaintメソッドのどのメッソドを
>オーバーライドするのでしょうか。

どれもオーバーライドしません。

<<<次に続きます>>>
    • good
    • 0

前回のコードをよく見てください。



Awtクラスのpaint()メソッドはシステムより呼び出されます。
これはいいでしょうか?


次にSwingクラスを見てみると、Awtを拡張(extends)しています。
つまり、「SwingクラスはAwtクラスである」とも言えます。
従って、Swingクラスもpaint()メソッドがシステムより呼び出されます。

しかし、Swingクラスでは、Awtクラスにはない機能(ボーダー描画等)を使用するため、
paint()メソッドでそれらの機能(ボーダー描画等)を定義し、
Awtクラスではpaint()メソッドで行うことは、paintComponent()というメソッドを用意し
このメソッド(paintComponent())で行うようにしてあります。


それぞれのクラスで独自描画をする場合どうなるかというと、
AwtクラスではMyAwtクラスのようにpaint()メソッドを直接上書き(オーバーライド)
しますが、SwingのクラスではMySwingクラスのように、paintComponent()メソッドの上書きになります。

MySwingクラスの動きを追ってみると、

1. Awtクラスで定義してあるpaint()メソッドがシステムより呼び出される
 (実際に動作するのは、Swingクラスで上書きしたpaint()メソッド)

2. Swingクラスで定義したpaint()の中のpaintComponent()が呼び出される。
 (実際に動作するのは、MySwingで上書きしたpaintComponent()メソッド)

となります。



MySwingクラスではボーダー処理などは何も記述していませんが、Swingクラスでボーダー処理が定義されているので、ボーダー機能を使用することができます。
MySwingクラスでボーダーの表示が出来るのは、Swingクラスのpaint()メソッドでpaintBorder()を呼び出しているためです。

ですので、例えば次のようなクラスを定義してしまうと、ボーダーが表示されません。

/** 独自Swingクラス2
*/
class MySwing2
  extends Swing
{

 @override
 public void paint(Graphics g){
  g.drawString("This is MySwing.", 100, 100);
 }

}

このクラスではSwigクラスのpaint()メソッドで定義してある
  paintBackground(g);
  paintComponent(g);
  paintChildren(g);
  paintBorder(g);
という処理を潰しています。


---------------------------------------
さて#5での質問ですが、以上の事がわかれば解決するかと思います。

まだわからないようであれば、再度ご質問ください。





なお、繰り返し指摘しますが、メソッドの上書きは

×オーバーロード
○オーバーライド

です。

オーバーロードというのは、同じ名前のメソッドを異なる引数により使い分ける機能のことです。

class Hoge
{
 public void show(int a){
  System.out.println("int");
 }

 public void show(Sring s){
  System.out.println("String");
 }
}

Hoge h = new Hoge();
h.show(1);
h.show("s");


実行結果
------
int
String
------

この回答への補足

ngsvxさん、回答有難うございます。

色々と回答を読ませていただいたのですが、全体の流れとしては、

【Awt】
・ 元々のAwtクラスのpaint();メソッドの中に書かれているメソッドの中は何もないので、
 ユーザーがAwtクラスを継承した子クラスのpaint();メソッドの中で、描画メソッドを
 オーバーライドして定義してやる。

【Swing】
・ Awtクラスを継承したSwingクラスは、paint();メソッド内にpaintComponentを含む他の
 メソッド(paintBorder、paintChildren)が元から定義されている。

・ ユーザーがSwingクラスを継承した子クラスで描画処理を行う場合には、親クラス
 (Swingクラス?)のpaintComponent();を呼び出し、その中にユーザーの設計する描画
 メソッドをオーバーライドして定義する。

という考え方でよいのでしょうか。


・ ここで再度別の疑問が湧いてくるのですが、

  ・ Swingクラスクラスを継承した子クラスの中で、
 
   【case 1】
    
    class JFrameTest1 extends JFrame
{
public static void main(String[] args)
{
myJPanel panel = new myJPanel();
JFrameTest1 mp = new JFrameTest1();

mp.add(panel);
mp.setVisible(true);
}
}

class myJPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.fillRect(50,50,100,100);
}
}
============================================================
と書いた場合には、親クラスSwingのpaint();メソッド内にある、paintComponent以外のメソッド
(paintBorder、paintChildren)は、当然呼び出されないという考えでよいのですか。
============================================================
   【case 2】

public class JFrameTest2 extends JFrame
{
public void paint(Graphics g)
{
super.paint(g);
g.drawString("ABC",100,100);
}

public static void main(String[] args)
{
JFrameTest2 jf = new JFrameTest2();
jf.setVisible(true);
}
}
============================================================
と書いた場合には、

  ・ super.paint(g);は、親クラスのpaint()内の全てのメソッドをオーバーライドしますが、そもそも、
   親クラスのpaint(g);内に定義されている全てのメソッドは、何個有るのでしょうか。
   また、それをどこからどのようにしてみることが出来るのですか。
    ( ngsvxさんの回答のなかでは、paintBackground(g);、paintComponent(g);、
     paintChildren(g);、paintBorder(g);の4個のメソッドが定義されていますが、
     私が調べたサイトでは、paintComponent(g);、paintChildren(g);、paintBorder(g);の
     3個のメッソドが定義されていると書かれていました。

      また、public void setBorder(Border border){}と、paintBorder(g);との使い分け
     みたいなものはあるのでしょうか。)

【続きを別の箇所に書かせていただきます。】 

補足日時:2010/10/09 21:17
    • good
    • 0
この回答へのお礼

  ・ g.drawString("ABC",100,100);は、Swing内のpaintメソッドのどのメッソドを
   オーバーライドするのでしょうか。
    それとも、

     ~
 public void paint(Graphics g)
 {
         ????     
paintComponent
paintChildren
paintBorder
g.drawString("ABC",100,100);
 }
     ~ 

 という内容になるのですか。

    それとも、Awt内のpaintメソッドをオーバーライドするのでしょうか。
    ( g.drawString("ABC",100,100);を書く場所は、Awtなら、 paint(Graphics g);内、
     Swingなら、paintComponentメソッド内というルールはないのでしょうか。)

・ Swingクラスのメソッドの中に、paintBackgroundというメソッドが書かれてありますが、
 元々のSwingクラスのpaint();メソッドの中に書かれているメソッドはどのような
 メソッドでしょうか。

  また、Awt、Swingクラスのコードをどのようにしたら見ることが出来るのでしょうか。


以上宜しくお願いいたします。

お礼日時:2010/10/09 21:20

少し具体的に説明します。



説明のため、AWTとswingの関係を表すためのイメージのコードを記載します。
(厳密にはこの通りではありません。あくまでもイメージです)



ーーーーーーーーーーーーーーーーーーーーーーー
/** AWT基本クラス
*/
class Awt
{

 public void paint(Graphics g){
 }

}



/** Swing基本クラス
*/
class Swing
  extends Awt
{

 @override
 public void paint(Graphics g){
  paintBackground(g);
  paintComponent(g);
  paintChildren(g);
  paintBorder(g);
 }

 /**外枠設定
  */
 public void setBorder(Border border){
  ~
  ~
  ~
 }

 /** 背景描画処理
  */
 protected void paintBackground(Graphics g){
  ~
  ~
  ~
 }


 /** コンポーネント内容描画処理
  * 独自のクラスで上書きしカスタマイズする
  */
 protected void paintComponent(Graphics g){
 }


 /** 子コンポーネント描画処理
  */
 protected void paintChildren(Graphics g){
  ~
  ~
  ~
 }


 /** 外枠描画処理
  */
 protected void paintBorder(Graphics g){
  ~
  ~
  ~
 }

}


/** 独自Awtクラス
*/
class MyAwt
  extends Awt
{
 @override
 public void paint(Graphics g){
  g.drawString("This is MyAwt.", 100, 100);
 }
}


/** 独自Swingクラス
*/
class MySwing
  extends Swing
{

 @override
 protected void paintComponent(Graphics g){
  g.drawString("This is MySwing.", 100, 100);
 }

}

ーーーーーーーーーーーーーーーーーーーーーーー

上のコードをよく見てください。


<<文字数制限のため、次に続きます>>
    • good
    • 0

まず、理解しておかなければならないのは、swingはawtの応用だということです。

(スーパークラスを遡るとawtのクラスがあるはずです)

つまり、awtで発生することはswingでも発生します。

したがって、awtでpaintメソッドが自動的に呼び出されるように、swingでもpaintメソッドが自動的に呼び出されます。

swingの機能てしてpaintメソッドでボーダーや子コンポーネントや独自の描画を行うようになっています。この仕組みで、共通の機能はコーディングせずにカスタマイズ可能となっています。

ですので、swingでは、どうしてもswingの機能を使いたくないなど、よほどの理由がない限りpaintメソッドを直接使うことはありません。
    • good
    • 0
この回答へのお礼

ngsvxさん、回答有難うございます。
再度質問ばかりで申し訳ないのですが、頭が悪くなかなか回答内容について
理解に至りません。宜しくお願い致します。

>したがって、awtでpaintメソッドが自動的に呼び出されるように、swingでもpaintメソッドが
自動的 に呼び出されます。

# 自動的に呼び出されるという意味は、awtでもswingでも、paint(g);と書いてやれば、
paint(g);が呼び出されるということでしょうか。


> swingの機能としてpaintメソッドでボーダーや子コンポーネントや独自の描画を行うよう
になっています。

# この意味が不明なのですが、

public void paintComponent(Graphics g)
{
g.setColor(Color.red);
g.fillOval(50,50,100,100);
}

と書いた場合には、paintBorder()、paintChildren()の2つのメッソドは、当然呼び
出されないという理解で良いのでしょうか。


> この仕組みで、共通の機能はコーディングせずにカスタマイズ可能となっています。
# 「共通の機能」とは、AWT、swingの描画という「共通の機能」のことを、指している
のでしょうか。

 また、「カスタマイズ可能」とは、paint(g){ }、paintComponent(g){ }メッソド内を呼
び出しオーバーロードすることが可能という意味でしょうか。


> swingでは、どうしてもswingの機能を使いたくないなど、よほどの理由がない限りpaint
 メソッドを直接使うことはありません。

# paintメソッドを直接使うという意味は、
 paintComponent(g)、paintBorder()、paintChildren()を個々に呼び出すという理解
 で良いのでしょうか。

以上宜しくお願いします。

お礼日時:2010/10/07 10:01

まず、ボーダーですがコンポーネントの縁というか外枠のことです。


swingでは、さまざまな種類のボーダーを設定できるようになっています。
どんなものがあるかは、実際に試してください。
comp.setBorder(BorderFactory.createXXXBorder());

次にpaintComponentの「独自の~」ですが、そのままの意味です。
JComponentなどを継承し新しいコンポーネントを作ろうとしたとき、そのコンポーネントの見た目を描画します。
例えばチェックボックスなら□とレなどを描画します。
ほとんどのコンポーネントで共通するであろう描画(ボーダーなど)はスーパークラスで描画し、そのコンポーネント独自の表現のみをpaintComponentで行うような設計になっているわけです。


そのため、残りの質問である「paintComponentだけで~」というのは、意味がないかと思います。
もっとも、paintComponentはprotectedなメソッドですので、関係のないパッケージから直接呼び出すことはできませんが。
    • good
    • 0
この回答へのお礼

 ngsvxさん、回答有難うございます。

 色々と参考書等で勉強をしていたら下のようなコードを見つけました。

 このコードは、paintComponent( )のみを呼び出しています。

 このとき、paintBorder、paintChildrenは当然呼び出されないと思うのですが、
どのような場合に、super.paint(g);を使うのか、また、どのような場合に

public void paintComponent(Graphics g)
{
g.setColor(Color.red);
g.fillOval(50,50,100,100);
}

という書き方になるのでしょうか、その使い分けがよく理解出来ません。
swingのpaint(g)をどのように使ったら良いのか、全くわかりません。
宜しくお願いします。

===================================================================

public class JFrame_Test extends JFrame
{
JFrame_Test()
{
this.setSize(300,200);
MyjPanel panel = new MyjPanel();
this.add(panel , BorderLayout.CENTER);
this.setVisible(true);
}

public static void main(String[] args)
{
new JFrame_Test();
}


class MyjPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(Color.red);
g.fillOval(50,50,100,100);
}
}
}

お礼日時:2010/10/06 21:31

まず、用語の使い方が正しくありません。


間違った使い方では、意味が通じませんので、気をつけてください。

オーバーロード
→今回のはオーバーライドです

エラーになります
→こういうのはエラーになるとは言いません。エラーになるという場合、大抵何らかのメッセージがでます。
今回のような場合は、「期待した通りの動作になりません」という表現になります。


さて、ご質問の回答ですが、まず使用している環境が違います。

A → AWT
B → swing

(それぞれの詳細は別途調べてください)


自分で描画する場合、AWTではpaintメソッドのオーバーライドで実装しますが、swingの場合はpaintComponentメソッドをオーバーライドすることになっています。

AWTと違いswingでは、背景や枠線等もswingの中で描画しています。
その作業はpaintメソッドで行われています。
そのため、paintメソッドをオーバーライドし、もともとの処理を省いてしまうと、背景の処理等が実行されません。

以上です。
    • good
    • 0
この回答へのお礼

 ngsvxさん、回答有難うございます。
 色々と参考書等で調べました。

 Swingのpaintの中には更に細かくメソッドがあり、
 ・paintComponent
   (コンポーネントの描画を行います、コンポーネントに独自の表示を行う場合、
    これを利用する。)
 ・paintBorder
   (コンポーネントのボーダーを描画します。)
 ・paintChildren
   (コンポーネント内に組み込まれているコンポーネントの描画を行います。)
との解説がありました。

 そこで再度質問なのですが、
  ・paintComponentのみを単独で呼び出して、描画する場合はあるのでしょうか。
   「コンポーネントに独自の表示を行う場合」とは、どのような場合でしょうか。
  ・paintBorder
   「コンポーネントのボーダー」とはどのようなものでしょうか。

 以上宜しくお願いします。

お礼日時:2010/10/05 21:23

手元の java 1.6.0_21 では, super.paint の呼び出しがなくてもそのような状況にはなってないですねぇ. 灰

色というかなんというか, 全面がそんな感じになってその中に指定した文字列だけが表示されてます.
    • good
    • 0
この回答へのお礼

 Tacosanさん、回答有難うございます。

 paint( )メッソドをオーバーロードしたときに、どのような場合に、super.paint( )で親クラスを呼んで
やる必要があるのでしょうか。
 また、その必要がない場合とはどのような場合なのでしょうか。

宜しくお願いします。

お礼日時:2010/10/04 20:15

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!