質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

3310閲覧

連続描写の方法

toutou

総合スコア2050

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/05/07 03:56

編集2017/05/09 00:44

どうしてもドラックしたときのイベントで連続描写すると隙間が開いてしまいます。forで1ずつ描写してもおかしいです。今のところ横だけのテストなんですがどこがおかしいのかわかりません。アドバイスをお願いします。

java

1import java.awt.BorderLayout; 2import java.awt.Color; 3import java.awt.Graphics; 4import java.awt.event.MouseEvent; 5import java.awt.event.MouseListener; 6import java.awt.event.MouseMotionListener; 7 8import javax.swing.JButton; 9import javax.swing.JFrame; 10import javax.swing.JPanel; 11public class Byou { 12 public static void main(String[] args){ 13 final Jframe body = new Jframe(); 14 body.setVisible(true); 15 final GPanel pen = new GPanel(); 16 body.add(pen); 17 } 18} 19 20class Jframe extends JFrame{ 21 public Jframe(){ 22 23 super("お絵かき"); 24 this.setBounds(600,600,500,500); 25 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 26 this.add(new GPanel(), BorderLayout.CENTER); 27 create_button(); 28 } 29 30 void create_button(){ 31 final JPanel migipane = new JPanel(); 32 final JButton a1 = new JButton("aa"); 33 final JButton a2 = new JButton("ee"); 34 migipane.setLayout(new BorderLayout()); 35 migipane.add(a1,BorderLayout.NORTH); 36 migipane.add(a2,BorderLayout.SOUTH); 37 this.getContentPane().add(migipane,BorderLayout.EAST); 38 } 39} 40class GPanel extends JPanel implements MouseListener, MouseMotionListener{ 41 private int move_x = -100; 42 private int move_y = -100; 43 private int start_x = -100; 44 private int start_y = -100; 45 private int x2; 46 private int y2; 47 private int xseve; 48 private int yseve; 49 public GPanel() 50 { 51 addMouseListener(this); 52 addMouseMotionListener(this); 53 setSize(300, 200); 54 } 55 56 @Override 57 public void paintComponent(Graphics g) 58 { 59 g.setColor(Color.BLUE); 60 g.fillOval(start_x, start_y, 10, 10); 61 } 62 63 @Override 64 public void mousePressed(MouseEvent e) 65 { 66 start_x = e.getX(); 67 start_y = e.getY(); 68 repaint(); 69 } 70 71 @Override 72 public void mouseClicked(MouseEvent e) 73 { 74 } 75 76 @Override 77 public void mouseReleased(MouseEvent e) 78 { move_x = -100; 79 move_y = -100; 80 start_x= -100; 81 start_y = -100; 82 repaint(); 83 84 } 85 86 87 @Override 88 public void mouseEntered(MouseEvent e) 89 { 90 } 91 92 @Override 93 public void mouseExited(MouseEvent e) 94 { 95 } 96 97 98//問題の部分 99 @Override 100 public void mouseDragged(MouseEvent e) 101 { 102 if(move_x <0) 103 { 104 move_x =e.getX(); 105 } 106 if(move_y < 0) 107 { 108 move_y = e.getY(); 109 } 110 repaint(); 111 xseve = move_defference(start_x,move_x); 112 yseve = move_defference(start_y,move_y); 113 if(xseve<0){ 114 for(int i= 0;xseve<i;i--) 115 { 116 start_x--; 117 repaint(); 118 } 119 } 120 start_x=e.getX(); 121 } 122 123 @Override 124 public void mouseMoved(MouseEvent e) 125 { 126 } 127 public int move_defference(int a,int b) 128 { 129 return a-b; 130 } 131}

修正部分
以下の通りに直しました。

java

1 @Override 2 public void paintComponent(Graphics g) 3 { 4 Graphics2D g2 = (Graphics2D)g; 5 BasicStroke BStroke = new BasicStroke(5.0f); 6 g2.setStroke(BStroke); 7 g.setColor(Color.RED); 8 if(start_x==-100||start_y== -10||move_x==-100||move_y==-100) 9 { 10 move_x = -100; 11 move_y = -100; 12 start_x= -100; 13 start_y = -100; 14 } 15 g.drawLine(start_x, start_y, move_x, move_y); 16 start_x = move_x; 17 start_y=move_y; 18 } 19 @Override 20 public void mousePressed(MouseEvent e) 21 { 22 start_x = move_x = e.getX(); 23 start_y = move_y = e.getY(); 24 } 25 @Override 26 public void mouseReleased(MouseEvent e) 27 { move_x = -100; 28 move_y = -100; 29 start_x= -100; 30 start_y = -100; 31 } 32 @Override 33 public void mouseDragged(MouseEvent e) 34 { 35 move_x = e.getX(); 36 move_y = e.getY(); 37 repaint(); 38 } 39 @Override 40 public void mouseClicked(MouseEvent e) 41 { 42 } 43 @Override 44 public void mouseEntered(MouseEvent e) 45 { 46 start_x = move_x = e.getX(); 47 start_y = move_y = e.getY(); 48 } 49 @Override 50 public void mouseExited(MouseEvent e) 51 { 52 move_x = -100; 53 move_y = -100; 54 start_x= -100; 55 start_y = -100; 56 } 57 @Override 58 public void mouseMoved(MouseEvent e) 59 { 60 } 61}

さらに追記

class GPanel extends JPanel implements MouseListener, MouseMotionListener{ private int move_x = -100; private int move_y = -100; private int start_x = -100; private int start_y = -100; private boolean flag = false; BufferedImage seve_field = new BufferedImage(600,600, BufferedImage.TYPE_4BYTE_ABGR); public GPanel() { addMouseListener(this); addMouseMotionListener(this); } @Override public void paintComponent(Graphics g) { Graphics2D g2= (Graphics2D)g; BasicStroke BStroke = new BasicStroke(5.0f); g2.setStroke(BStroke); g2.setColor(Color.RED); Graphics seve = seve_field.createGraphics(); Graphics2D seve2= (Graphics2D)seve; seve2.setStroke(BStroke); seve2.setColor(Color.RED); if(start_x==-100||start_y== -100||move_x==-100||move_y==-100) { move_x = move_y = start_x = start_y = -100; } g2.drawImage(seve_field,0,0,this); seve2.drawLine(start_x, start_y, move_x, move_y); g2.drawLine(start_x, start_y, move_x, move_y); start_x = move_x; start_y = move_y; } @Override public void mousePressed(MouseEvent e) { flag =false; start_x = move_x = e.getX(); start_y = move_y = e.getY(); } @Override public void mouseReleased(MouseEvent e) { flag = true; move_x = move_y = start_x = start_y = -100; } @Override public void mouseDragged(MouseEvent e) { move_x = e.getX(); move_y = e.getY(); repaint(); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseMoved(MouseEvent e) { }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

イベントハンドラー(本件の場合はmouseDragged)の中で画面を複数回再描画させようとするのはJavaでは間違いです。(Javaに限らずイベントドリブンなGUIシステム、つまりほとんどのGUIシステムで同様です)

単一のイベントハンドラーでは状態の変更とただ一回のrepaintの呼び出しのみが許されると思ってください。複数回repaintを呼び出してもpaintComponentメソッドは一度しか呼び出されません。つまりrepaintを呼び出したら即座に再描画されるという前提そのものが成り立たないんですね。

repaintの意味(機能)は「近い将来(といっても1msec未満の未来と思ってよいです)何もイベントが発生していないヒマな時間に任意のタイミングでpaintComponentが呼び出されるようにswingのランタイムに命令する」というふうに考えるとよいです。

質問者さんのコードでは「以前のマウスの場所から新たにドラッグされた場所まで座標を少しずつずらしながら10x10の円を描画する」ということを意図してますが、「少しずつずらしながら描画する」という部分はpaintComponentの中自体で行ってみてください。

フィールドには次のような情報を覚えておくとよいと思います。

  • lastMouseX, lastMouseY

最後に円を描画した位置という意味合い。この座標はmousePressedイベントで設定するとよいでしょう。

  • newMouseX, newMouseY

新たにドラッグを検出した際のマウス位置。mousePressedイベントの際にはlastMouseX, lastMouseYと同じ値にしておくとよいでしょう。

paintComponentではlastMouseX/YとnewMouseX/Yの座標が異なっていた場合のみlastMouseX/Y->newMouseX/Yに向かって円を描画し、描画し終わったらlastMouseX/Yの値をnewMouseX/Yと同じ値に書き換えるというようにしておけばよいでしょう。


追記:上記の回答とは別の話になりますが、修正後コードを動かしてみて気づいた点をいくつか指摘しておきます。

  • 書いた絵の情報を記録していない

一応絵は描けますが、ウィンドウを最小化してから再表示してみてください。せっかく書いた絵が消えていることに気づくと思います。描画した絵の内容はBufferedImageなどに記録しておき、paintComponentではBufferedImageの内容をdrawImageするだけというのが本来のお絵かきソフトの作りになると思います。

  • mouseEntered/mouseExited

わかりやすさのために座標の設定を行っているとは思うのですが、実際にはこのイベントの処理は(ドラッグによる線の描画に関しては)不要です。

  • レイアウトのしかた

setBounds/setSizeで直接大きさを指定することとLayoutManager(BorderLayout)を併用しているのは画面がくずれる原因になると思います。自分の環境(Windows10 JDK1.8.0_131)では絵を書いたときにボタンがおかしな位置(左上)に描画されてしまいます。

投稿2017/05/07 04:47

編集2017/05/09 04:11
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toutou

2017/05/08 00:06

ありがとうございます。いろいろ修正し出来たものを、追記で上のほうに乗せておきます。 説明自体の意味はわかりやすかったのですが、それを実現する方法がまったくわからず苦戦しました。結局自分ではうまく出来ず、丸を描写するのでなく線を引く方法に変更しました。残った問題点としては、端っこに少し隙間が開いてしまうというのがありますが、後々直そうかと思います。端っこに行ったときに、座標を-1にして画面外から線を引こうかと。出来たらもう少しアドバイスがほしいので、まだ開けておき、しばらくしたら解決済みにしようと思います。
KSwordOfHaste

2017/05/08 03:11

直線の補完は修正後ソースの通りStrokeを設定し直線で描画する方がより適切だと思います。 > 座標を-1にして画面外から線を引こうかと 端に隙間はできないように思えますが? 実際に動かしてみましたが、他に気になる点がありますのでいくつか回答へ指摘しておきます。
toutou

2017/05/09 00:58 編集

ありがとうございます。 修正したのを上に載せておきました。 端の線はそちらの環境ではなってないということなので、こちらの環境で何かおかしな部分があるのでしょう。 新たに最大化してすばやく横に動かすと、出発地点によっては時々書けないという謎の問題も発覚しましたが、これは今のところそこまで問題ではないので、後々にします。 記録機能は後々つけるつもりでしたが、せっかくの機会ですのでやってみました。 BufferedImagやdrawImageの意味がわかりませんでしたが、調べて何とかしました。 イベント処理は少なくしました。 レイアウトについては今のところ自分で使うつもりなのでそこまで問題ではないのと、そこまで手が回らないので後々にしようかと思います。 今、buttonのイベントに少しあたふたしてますので、また別で質問を立てるかもしれません。
edoooooo

2017/05/09 06:02 編集

削除します。
swordone

2017/05/09 03:50

本当に関係ないですね。その回答のコメントに書くべきでは。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問