サブクラス化する

JFrame でサブクラス化(MyClass)して矩形を描画します。

前田稔の超初心者のプログラム入門

プログラムの作成

  1. new で生成する では Canvas をサブクラス化しましたが、何も Canvas に限りません。
        MyCanvas canvas = new MyCanvas();
            ・・・
    
        // MyCanvas Class
        class MyCanvas extends Canvas
        {   public void paint(Graphics g)
            {   g.setColor(Color.red);
                g.drawRect(10,10,120,50);
            }
        }
        
    このページでは Canvas 以外を使う方法を説明します。
  2. JFrame でサブクラス化(MyClass)して矩形を描画します。
    //★ JFrame でサブクラス化(MyClass)して矩形を描画    前田 稔
    import java.awt.*;
    import javax.swing.*;
    
    public class AppNew
    {   // Main()
        public static void main(String argv[])
        {   AppNew app = new AppNew();
        }
    
        // Constructor
        AppNew()
        {   JFrame jframe = new JFrame("View JFrame");
            jframe.setSize(130,120);
            jframe.setLayout(new BorderLayout());
            MyClass myclass = new MyClass();
            jframe.add(myclass, BorderLayout.CENTER);
            jframe.setVisible(true);
        }
    }
    
    //☆ MyClass Class
    class MyClass extends Canvas
    //class MyClass extends JPanel
    //class MyClass extends Panel
    //class MyClass extends JComponent
    //class MyClass extends Container
    {   public void paint(Graphics g)
        {
            g.setColor(Color.red);
            g.drawRect(10,10,120,50);
        }
    }
    
  3. java のソースファイルをコンパイルして class オブジェクトを実行して下さい。

プログラムの説明

  1. 基本的な説明は new で生成する を参照して下さい。
    Canvas, JPanel, Panel, JComponent, Container を順番に試して下さい。
    全てのコンポーネントで矩形が描画されるはずです。
    取りあえず心当たりを並べて試したのですが、探せば幾らでも出てきそうです。
        //☆ MyClass Class
        class MyClass extends Canvas
        //class MyClass extends JPanel
        //class MyClass extends Panel
        //class MyClass extends JComponent
        //class MyClass extends Container
        {   @Override public void paint(Graphics g)
            {
                g.setColor(Color.red);
                g.drawRect(10,10,120,50);
            }
        }
        
  2. 今回は JFrame(Swing)で説明しましたが、当然 Frame(AWT)を使う方法もあります。
    Java のプログラムの組み方は千差万別で、このことが返ってプログラムを解り難くしているのでは無いでしょうか? (^_^;)
    「矩形の描画アラカルト」では、矩形を描画する方法を幾つか説明してきましたが、あなたはどの方法がお好みですか。

【NOTE】

Canvas 以外にも様々なコンポーネントをサブクラス化する方法を紹介しましたが、言うなればこれらのコンポーネントは全て paint() メソッドを持っていることになります。
レベルの違うコンポーネントがそれぞれ paint() メソッドを持っていると言うことは、そのふるまいと従属関係が重要になります。
  1. クラス Container
    一般的な Abstract Window Toolkit (AWT) コンテナオブジェクトは、ほかの AWT コンポーネントを含むことができるコンポーネントです。
    コンテナに追加されるコンポーネントはリスト中に入れられます。
    リストの順番は、コンテナ中の前面から後面へコンポーネントがスタックされる順番を表します。
    コンテナにコンポーネントを追加するときにインデックスが指定されないと、リストの最後尾に追加され、最後尾にスタックされます。
    paint() メソッドはコンテナをペイントします。
    このコンテナの子コンポーネントであるすべての軽量コンポーネントへ描画要求を転送します。
    このメソッドが再実装される場合、軽量コンポーネントが正しく描画されるように super.paint(g) が呼び出されなければなりません。
    子コンポーネント全体が、g で設定される現在のクリッピングによってクリップされる場合、paint() はその子コンポーネントには転送されません。
  2. クラス JComponent
    トップレベルのコンテナを除くすべての Swing コンポーネントの基底クラスです。
    JComponent から継承するコンポーネントを使用するには、ルートがトップレベルの Swing コンテナである包含関係の階層にコンポーネントを位置付ける必要があります。
    JFrame、JDialog、JApplet などのトップレベルの Swing コンテナは、他の Swing コンポーネントがそれ自身を描画するための場所を提供する特殊なコンポーネントです。
    コンポーネントを印刷するには、paint() メソッドを呼び出します。
    このメソッドは printComponent、printBorder および printChildren を呼び出します。
    このメソッドをオーバーライドすることは推奨されないので、代わりに前述のメソッドのどれかをオーバーライドします。
    このメソッドでは、コンポーネントをダブルバッファリングを使用しない状態、つまりペイントが Graphics の受信側で直接行われる状態に設定します。
  3. クラス Panel
    Panel はもっともシンプルなコンテナクラスです。
    パネルは、ほかのパネルなどのさまざまなコンポーネントを貼り付けるためのスペースをアプリケーションに提供します。
    paint() メソッドはクラス java.awt.Container から継承しています。
  4. クラス JPanel
    JPanel は、汎用の軽量コンテナです。
    paint() メソッドはクラス javax.swing.JComponent から継承しています。
  5. クラス Canvas
    Canvas コンポーネントは、アプリケーションが描画したり、ユーザからの入力イベントをトラップしたりすることができる空白の矩形の画面領域を表します。
    カスタムコンポーネント生成などの便利な機能を使うためには、アプリケーションで Canvas クラスをサブクラス化する必要があります。
    キャンバスでカスタムグラフィックスを実行するためには、paint メソッドをオーバーライドする必要があります。
    paint() メソッドはこのキャンバスをペイントします。
    Canvas をサブクラス化するほとんどのアプリケーションでは、便利な操作を実行するためにこのメソッドをオーバーライドすることになります。
    キャンバスのカスタムペイントが典型的な例です。
    既定の操作は単純なキャンバスのクリアです。
    このメソッドをオーバーライドするアプリケーションでは、super.paint(g) を呼び出す必要はありません。
実の所この関係が複雑で、現在の所 super.paint(g) を呼び出すタイミングを把握できていません。
様々なケースで super.paint(g) を呼び出すタイミングを試して下さい。
//☆ MyClass Class
class MyClass extends Canvas
//class MyClass extends JPanel
//class MyClass extends Panel
//class MyClass extends JComponent
//class MyClass extends Container
{   @Override public void paint(Graphics g)
    {
        //super.paint(g);
        g.setColor(Color.red);
        g.drawRect(10,10,120,50);
        //super.paint(g);
    }
}

・paint() の先頭で super.paint(g) を呼ぶ
・paint() の後部で super.paint(g) を呼ぶ
・super.paint(g) を呼ぶ必要は無い

超初心者のプログラム入門(Java2)