Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

Java初心者です.Swingでドラッグ描画できない

JavaのおもにSwingを使ってペイントっぽい機能をもったGUIをつくっている途中です.

以下は現在のコードです.

http://ideone.com/3rcXka

上記のコードですが,
フレームの中にペイントパネルを作って,
その範囲内ドラッグで描画を行い,書いた絵の座標を配列に格納するだけのプログラムを作ったつもりなのですが

点が,最後にマウスを離した1点しか描画されません.

連続的に点を描画して線画を出力したいのですができません.

super.paintComponentをコメントアウトすると連続的に描画できるのですが,パネル背景の白が塗られなかったり,パネルの枠が二重になったりと出力がバグってしまいます.

Java初心者でわからないことが多く,Swingの描画についてもあまり理解できていないのだと思います.
正しいコードや,上記バグの原因など,教えていただければ幸いです.

2

回答

93276

閲覧

2件の回答

評価

30

重要な点のみ残し元のコードを一部省略して書きます。

public class Main extends JPanel implements 
MouseMotionListener {
  int[][] FullPoint = new int[2][1000];
  int i = 0;

  public Main() {
    ...
    setBackground(Color.WHITE);
    addMouseMotionListener(this);
  }

  public void mouseDragged(MouseEvent e) {
    FullPoint[0][i] = e.getX();
    FullPoint[1][i] = e.getY();
    repaint();
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.fillOval(FullPoint[0][i], FullPoint[1][i], 5, 
5);
    i += 1;
  }

  ...
}

>点が,最後にマウスを離した1点しか描画されません.

 コンポーネント上に表示すべデータをモデルと呼びま
す。ここでは描画すべき点の座標の配列FullPointと点の
数を表すiです。モデルはそれを変更する契機(この場合
はマウスのドラッグ)で変更すべきであり、
paintComponentで変更すべきではありません。また、
paintComponentはモデルの変化分(差分)だけを描画するの
ではなくモデル全体を描画すべきです。つまりメソッドが
呼び出される度に毎回全ての点を描画しなければなりませ
ん。


>super.paintComponentをコメントアウトすると...
詳しくはJComponentのpaintComponentの説明を理解しない
といけないのですが、大雑把にいえばとりあえず無条件に
呼び出しておけばいいです。また本来は背景色を明示的に
設定して背景を塗りつぶしたいのならsetBackgroundだけ
でなく、setOpaque(true)でこのコンポーネントを不透明
としておく必要があります。さもないとデフォルトの背景
色になってしまいます。

以上を踏まえてコードを変更すると以下のようになりま
す。(チェックなどは省略)

public class Main extends JPanel implements 
MouseMotionListener {
  int[][] FullPoint = new int[2][1000];
  int i = 0;

  public Main() {
    ...
    setBackground(Color.WHITE);
    setOpaque(true);
    addMouseMotionListener(this);
  }

  public void mouseDragged(MouseEvent e) {
    // モデルの変更はここでのみ行う
    FullPoint[0][i] = e.getX();
    FullPoint[1][i] = e.getY();
    i++;
    repaint();
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    // モデル全体を描画する
    for (int index = 0; index < i; index++) {
      g.fillOval(FullPoint[0][index], FullPoint[1]
[index], 5, 5);
    }
  }

  ...
}


なおMainはJPanelの派生にしてますが、子供コンポーネン
トを配置してないのでJPanelにする必要はなく単に
JComponentの派生でよいと思います。表示結果だけみると
違いは見えないですけど。

評価

0

質問者です.

     
KSwordOfHaste 様,
丁寧なご回答,本っっっっっっ当にありがとうございます.

おかげで,うまく描画できました.

勘違いしている部分や,使い方を間違っている部分に気づけました.

やり方が分からなくて途方にくれていたので感謝しています.

理解できた部分をいかして,もっと詳しく調べ,これからもJavaをがんばります.

本当にありがとうございました.

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。