- ベストアンサー
アプレットで簡単な絵を描きたい
- drawLineメソッドを使用してマウスで絵を描きたいのですがうまくいきません。
- どうすればいいでしょうか?
- 一応私が途中まで考えたソースを下に載せておきます。できればこのソースを変更して完成できればよく理解できるのでよろしくお願い致します。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 >それと、私が最初drawLineを使用して線の描画を行おうと >しましたがそれでは無理なのでしょうか? >一応VB.NETではdrawLineを使用して絵を描いたの >でできるかと思いまして。 VB.netのことはよくわからないのですが、昔のVBではフォームのlineメソッドとかでやっていたような気がします。 今思えば、こういったことをフォームが内部的にやってくれていたということでしょうね。 とにかく、Javaのコンポーネントのpaintメソッドでは全部を描かないといけないので、何らかの方法で、今まで描いてきた絵を覚えておく必要があります。 オフスクリーンバッファを使わない方法も考えてみました。 今まで描いてきた履歴をLineオブジェクトDrawnStringオブジェクトとして記憶し、paintメソッドで一気に書くという方法です。 これだと、拡大や縮小にも対応できますし、Undoも簡単です。 import java.awt.*; import java.applet.*; import java.awt.event.*; import java.util.*; public class MyGraphics4 extends Applet implements ActionListener, MouseListener, MouseMotionListener { //描画要素を保存しておくVector Vector drawList; int startX, startY; //背景を塗りつぶすかつぶさないかのフラグ boolean isClearBackground = false; //文字を書くボタン Button stringButton; //手前で描いた要素を削除するボタン Button deleteButton; public void init(){ setLayout(new FlowLayout()); stringButton = new Button("文字列"); stringButton.addActionListener(new StringButton_Clicked()); add(stringButton); deleteButton = new Button("削除"); deleteButton.addActionListener(this); add(deleteButton); addMouseListener(this); addMouseMotionListener(this); drawList = new Vector(); } public void actionPerformed(ActionEvent e) { //deleteButtonのイベントハンドラ //最後の描画要素を削除して drawList.remove(drawList.size() - 1); //背景更新モードでrepaint isClearBackground = true; repaint(); } public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ startX = e.getX(); startY = e.getY(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); //リストに新しい線分を追加 Line line = new Line(startX, startY, x, y); drawList.add(line); repaint(); startX = x; startY = y; } public void update(Graphics g) { if (isClearBackground) { //背景更新する場合はスーパークラスのupdateを呼ぶ super.update(g); isClearBackground = false; } else //そうじゃない場合はそのままpaintにつなぐ。 paint(g); } public void paint(Graphics g) { //すべての要素を描画 for (int i = 0; i < drawList.size(); i++) { Drawable drawnObject = (Drawable)drawList.get(i); drawnObject.draw(g); } //ボタンを追加したので、これを呼んでおかないと、ボタンが表示されない super.paint(g); } private class StringButton_Clicked implements ActionListener { //stringButtonのイベントハンドラ int x = 0; int y = 30; public void actionPerformed(ActionEvent e) { //文字要素をリストに追加 drawList.add(new DrawnString("MyGraphics4の", x, y)); y+=10; repaint(); } } } //------------------------- public interface Drawable { public void draw(java.awt.Graphics g); } //----------------------------- public class Line implements Drawable { public int x1, y1, x2, y2; public Line() {}; public Line(int x1, int y1, int x2, int y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public void draw(java.awt.Graphics g) { g.drawLine(x1, y1, x2, y2); } } //------------------------------------ public class DrawnString implements Drawable { public String string; public int x, y; public DrawnString() {} public DrawnString(String string, int x, int y) { this.string = string; this.x = x; this.y = y; } public void draw(java.awt.Graphics g) { if (string != null) { g.drawString(string, x, y); } } }
その他の回答 (2)
- PecoPlus
- ベストアンサー率76% (144/188)
こんばんは、#1です。 >ダブルバッファリングとはどのようなものでしょうか? うーん、今回のような使い方はダブルバッファリングとは言わないのかも。 ここ↓のページがわかりやすいので、読んでみてください。 http://hp.vector.co.jp/authors/VA012735/java/dbuf1.htm ちらつき防止のためにあるものですが、今回は描いた絵を覚えておかないといけないので、オフスクリーンバッファに線を描いていき、paintメソッドでdrawImageを使って一気に描画します。 >「"APPLETの"」を起動時に表示させ、それから線を描きたいのですが、 >、「"APPLETの"」が消えてしまいます。どうすればいいでしょうか? initメソッド内でオフスクリーンバッファに書いておけばよいと思います。 >一応updateメソッドにて線を描きなさいという条件があるので >直させていただきました。(ちゃんと動きます) なんだか、変な条件ですが、これだと、うまくいかないはずです。 MyGraphics3アプレットを起動してみてください。 適当に線を描き、ブラウザを最小化して、元に戻してみてください。 線が消えてしまうはずです。 そして、再び線を描こうとすると、突然今まで描いた線が現れます。 これは、想定した挙動ではないはずです。 update()はrepaint()によって呼び出されます。 repaint() → update() → paint() つまり、update()はプログラムの中で明示的にrepaint()を呼ばないと実行されません。 イベント処理スレッドは直接paint()を呼ぶので、updateに描画するコードを書くとシステムによる描画に対応できません。 paintメソッドで描いたほうがいいと思うのですが・・・。 import java.awt.*; import java.applet.*; import java.awt.event.*; public class MyGraphics2 extends Applet implements MouseListener, MouseMotionListener { //ダブルバッファリング用のイメージ Image imageBuf; //そのイメージのグラフィックオブジェクト Graphics imageBufG; private int startX; private int startY; public void init(){ addMouseListener(this); addMouseMotionListener(this); //ダブルバッファリング用のイメージの作成 imageBuf = createImage(getWidth(), getHeight()); //そのグラフィックオブジェクトの取得 imageBufG = imageBuf.getGraphics(); imageBufG.setColor(Color.BLACK); imageBufG.drawString("APPLETの", 10, 150); } public void stop(){} public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ System.out.println("press"); startX = e.getX(); startY = e.getY(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); //ダブルバッファリング用のイメージに書き込む imageBufG.drawLine(startX, startY, x, y); repaint(); startX = x; startY = y; } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(imageBuf, 0, 0, this); } }
補足
詳しい回答ありがとうございます。 確かにupdateメソッドに処理を記述すると実行結果が変ですね。ダブルバッファリングのこともよく分かってよかったです。 それと、私が最初drawLineを使用して線の描画を行おうとしましたがそれでは無理なのでしょうか? 一応VB.NETではdrawLineを使用して絵を描いたのでできるかと思いまして。 何度も質問して申し訳ありませんが、回答のほどよろしくお願い致します。
- PecoPlus
- ベストアンサー率76% (144/188)
こんばんは。 いろいろ問題点があります。 1.paintメソッドではなく、updateメソッドで描画しようとしている。 2.仮にpaintメソッドで描画していても、ダブルバッファリングができていないので、このままでは、点が移動するだけで、絵にならない。 3.mouseMovedを使っているが、MouseMotionListenerをimplementsしていないため、独自メソッドになってしまっている。 4.addMouseMotionListenerを登録していない。 5.そもそもmouseDraggedを使うべき。 などなどでしょうか。 サンプルを書くとこんな感じです。 import java.awt.*; import java.applet.*; import java.awt.event.*; public class MyGraphics2 extends Applet implements MouseListener, MouseMotionListener { //ダブルバッファリング用のイメージ Image imageBuf; //そのイメージのグラフィックオブジェクト Graphics imageBufG; private int startX; private int startY; public void init(){ addMouseListener(this); addMouseMotionListener(this); //ダブルバッファリング用のイメージの作成 imageBuf = createImage(getWidth(), getHeight()); //そのグラフィックオブジェクトの取得 imageBufG = imageBuf.getGraphics(); imageBufG.setColor(Color.BLACK); } public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ System.out.println("press"); startX = e.getX(); startY = e.getY(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); //ダブルバッファリング用のイメージに書き込む imageBufG.drawLine(startX, startY, x, y); repaint(); startX = x; startY = y; } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { //ダブルバッファリング用のイメージを描画する。 g.drawImage(imageBuf, 0, 0, this); } }
お礼
回答ありがとうございます。 ダブルバッファリングとはどのようなものでしょうか? 後もうひとつ要望があるのですが、「"APPLETの"」という文字をアプレット起動時に表示させる処理を追加しました。これが線を描いたときに消えてしまいます。 一応条件としては、「"APPLETの"」を起動時に表示させ、それから線を描きたいのですが、、「"APPLETの"」が消えてしまいます。どうすればいいでしょうか? 一応updateメソッドにて線を描きなさいという条件があるので直させていただきました。(ちゃんと動きます) 回答のほどよろしくお願い致します。 import java.awt.*; import java.applet.*; import java.awt.event.*; public class MyGraphics3 extends Applet implements MouseListener, MouseMotionListener { //ダブルバッファリング用のイメージ Image imageBuf; //そのイメージのグラフィックオブジェクト Graphics imageBufG; private int startX; private int startY; public void init(){ addMouseListener(this); addMouseMotionListener(this); //ダブルバッファリング用のイメージの作成 imageBuf = createImage(getWidth(), getHeight()); //そのグラフィックオブジェクトの取得 imageBufG = imageBuf.getGraphics(); imageBufG.setColor(Color.BLACK); } public void stop(){} public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ System.out.println("press"); startX = e.getX(); startY = e.getY(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); //ダブルバッファリング用のイメージに書き込む imageBufG.drawLine(startX, startY, x, y); repaint(); startX = x; startY = y; } public void update(Graphics g) { g.drawImage(imageBuf, 0, 0, this); } public void paint(Graphics g) { g.drawString("APPLETの", 10, 150); } }
お礼
回答ありがとうございます。 ソースを毎回考えていただき申し訳ない限りです。 とりあえず、いろいろなやり方があるんだなということが分かり大変参考になりました。 本当にありがとうございます。