Scrollペインのグラフィックス

  1. グラフィックパネル
    1. グラフィックス
       SwingでもAWTと同様のグラフィックスメソッドは利用できます。ただし、swingの部品を利用している場合、paint() の先頭で、
       super.paint(g);
      を呼び出す必要があります。Swingでは paint() で、各種の描画処理をしているため、paint()をオーバーライトすると、他の処理ができなくなるためです。

    2. パネルへの描画
       アプレットの画面の中にサブウインドウとして「パネル:JPanel」を組み込むことができます。アプレットのウインドウ全体でなく、パネルに描画をするとパネル外部への描画は抑制されるため、パネル外へのはみ出しを心配する必要はありません。パネル等の部品への表示は、getGraphics();で グラフィックスgpを取得し、
        Graphics gp=jPanel1.getGraphics();
      gpに描画を行ないます。この場合の座標系の原点は、jPanel1の原点となります。AWTのPanelではグラフィックスが利用できません。

    3. スクロール可能なパネル
       パネルをスクロールペインに組み込むと、スクロール可能なグラフィックが実現できます。例えば 400*400 のサイズのパネルを200*200のスクロールペインに組み込みと、パネルへの400*400のサイズのグラフィック表示は、スクロールに従い200*200の窓に表示されます。

  2. マウス座標
    1. マウス座標の取得
      インターフェースを利用してマウス関連メソッドを組み込む場合、すべての関数を定義する必要があります。Jbuilderで、マウスの mousePressed() のみに対応するメソッドを組み込む場合、アップレットのウインドウを選択し、左のインスペクタペインでイベントタブを選択し mousepressed を選択すると、匿名クラスで 次のようなmousePressed 対応メソッドを組み込んでくれます。
          this.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
              this_mousePressed(e);
            }
          });

    2. マウスイベント
       アプレットにスクロールペインを組み込んだ場合、スクロールペイン内部でのマウスイベントは発生しません(ただし、JDK1.3では発生しますから注意して下さい)。スクロールペインでのイベントを処理するには、上記の匿名クラスのthisをスクロールクラスのオブジェクトに変更します。

          jScrollPane1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
              this_mousePressed(e);
            }
          });

       マウスイベントはマウスの座標は、スクロールペインからの相対座標になります。スクロールペイン内部のパネルの原点は、スクロールペインのスクロール状態で変化します。部品の親ウインドウ相対の矩形座標は getBounds() で取得できます。矩形座標から getLocation() で、矩形原点の座標を取得できます。
       
          Rectangle rctpnl=jPanel1.getBounds();
          Point poff=rctpnl.getLocation();
          pt.x=e.getX()-poff.x;
          pt.y=e.getY()-poff.y;

      ここで、eはマウスイベントで渡される MouseEvent です。Jbuilder7では 内部のスクロールペインに対するマウスイベントには対応していませんから、一度、アプレットウインドウに対するメソッドを生成し、this を 書き換えると簡単です。

  3. 不定個数を扱うベクタ
    1. ベクタクラス
      ベクタクラスは不定個数のオブジェクトを記録し、順に取り出すことができます。また、配列のように指定した要素を取り出すことも可能です。

    2. 定義と繰返しメソッド
      ベクタは次のように定義します。
       Vector cv=new Vector();
      ベクタは任意のクラスのオブジェクトを記録できます。オブジェクト pt を記録するには
       cv.add(pt);
      とします。記録されたベクタを順に取り出すには Iteratorクラス を利用できます。iterator()でIteratorのオブジェクト it を生成します。it.next() で次のオブジェクトを取得できます。また、hasNext() で要素が残っているか判断できます。it.next() で取り出したオブジェクトはクラスが不明です。 ここでは Point クラスなので、(Point)でキャスト(型指定)をしています。
          Iterator it=cv.iterator();
          while(it.hasNext()){
            Point pt=(Point)it.next();
         g.drawOval(pt.x-10,pt.y-10,20,20);
          }
    3. ベクタの要素の配列型アクセス
       ベクタの要素は i を整数として elementAt(i) でi 番目の要素を取り出すことができます。ベクタの要素数は size() で取得できますから

       for(int i=0; i < cv.size();i++){
        Point pt = (Point) cv.elementAt(i);
       }

      で、繰返し処理ができますが、すべての要素を取り出す場合は、Iterator クラスを利用する方が効率的です(多分)。

  4. プロジェくト

    1. 目的
       アプレットウインドウに Draw with Scroll を表示します。
       また、スクロールペインの内部でマウスをクリックすると円を表示します。スクロールをしながらスクロールペインより大きなパネルに、円を記録できます。

    2. レイアウト
      JBuilderでスクロールペインを組み込み、その中にパネルを組み込みます。パネルのプロパティで preferredSize を 400,400 に設定し、パネルのサイズを設定します。パネルのサイズがスクロールペインより大きいと、スクロール用のスライダが現れます。
          jPanel1.setPreferredSize(new Dimension(400, 400));
        jScrollPane1.setBounds(new Rectangle(183, 27, 185, 218));
          this.add(jScrollPane1, null);
          jScrollPane1.getViewport().add(jPanel1, null);

    3. スクロールイベントの利用
       次のように、スクロールペインでパネルをスクロールしたとき、発生するイベントを処理するメソッドを生成します。
      Jbuilder7では、自動生成できません。
          jPanel1.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentMoved(ComponentEvent e) {
              jPanel1_componentMoved(e);
            }
          });

    4. マウス処理
       マウスでクリックした位置を、スクロールペイン原点相対座標に変換して ベクタ で記録します。
      座標は、スクロールの程度でも変化します。座標をベクタに追加後、再表示します。
        void this_mousePressed(MouseEvent e) {
          Point pt=new Point(0,0);
          Rectangle rctpnl=jPanel1.getBounds();
          Point poff=rctpnl.getLocation();
      
          pt.x=e.getX()-poff.x;
          pt.y=e.getY()-poff.y;
      
          cv.add(pt);
          repaint();
        }

      cvは 予め Vector cv=new Vector(); で定義しておきます。このままでは、表示可能範囲外でも位置をベクトルに保存します。クリック位置の確認をする方が良いでしょう。

    5. 描画処理
       (10,20)の位置に、文字列を描画します。ベクタの座標を取り出し、jPanel1 に描画します。
        public void paint(Graphics g){
          super.paint(g);
          g.drawString("Draw with Scroll",10,20);
          Iterator it=cv.iterator();
          while(it.hasNext()){
            Point pt=(Point)it.next();
            Graphics gp=jPanel1.getGraphics();
            gp.drawOval(pt.x-10,pt.y-10,20,20);
          }
        }

  5. 実行
     スクロール領域の内部でクリックすると、その位置を中心に円を描きます。グラフィックスはスライダでスクロールが可能です。位置を戻すと、先に作成した円が描画されます。



  6. 別クラスで組み込む
     スクロールが不要な場合、JPanelを継承したクラスを、新規クラスとして組み込むこともできます。マウス処理も新規のクラスで実行できますから、この方がモジュールとしての独立性は高くなります。