![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
Javaアップレットについて質問です。マウスをドラッグすると、マウスによって指定した位置に長方形を描き、Shiftキーを押したまま描かれた長方形の内部でドラッグすると、マウスを移動した距離だけ長方形を移動させる、というプログラムを作りたいのですが
Shiftキーを押したまま長方形の内部でドラッグすると、描いた長方形が消えてしまいます。
どうしていいかわからないので、改善点がありましたら教えてください。
なお、最初に長方形を描くところはできています。
プログラムは以下のとおり
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class ex1123 extends Applet implements MouseListener, MouseMotionListener{
//Shiftキーを押しているかどうか
boolean isS = false;
//マウスが長方形の内部に入っているかどうか
boolean enter = false;
//長方形
Rectangle r1 = new Rectangle(0,0,0,0);
//Shiftキーを押したまま、マウスを押した位置と離した位置
Point p1;
Point p2;
public void init(){
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint(Graphics g){
if(!r1.isEmpty()){
if(isS){
//マウスが長方形の内部にはいっていたら移動させる
if(enter){
//長方形の始点を移動させる
r1.x = r1.x + (p2.x - p1.x);
r1.y = r1.y + (p2.y - p1.y);
g.drawRect(r1.x, r1.y, r1.width, r1.height);
}
}
else{
g.drawRect(r1.x, r1.y, r1.width, r1.height);
}
}
}
public void mousePressed(MouseEvent e){
r1.setLocation(e.getPoint());
r1.setSize(0,0);
if((e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) ==
MouseEvent.SHIFT_DOWN_MASK){
isS = true;
//マウスが長方形の内部に入っているかどうか
enter = r1.contains(e.getPoint());
if(enter){
//p1はマウスを押した位置, p2はnull
p1 = e.getPoint();
p2 = null;
}
}
else{
isS = false;
}
repaint();
}
public void mouseDragged(MouseEvent e){
//マウスの位置
1if(enter)
p2 = e.getPoint();
//最初に描く長方形のサイズを決める
r1.setSize(Math.abs(e.getX() - r1.x), Math.abs(e.getY() - r1.y));
repaint();
}
public void mouseReleased(MouseEvent e){
//マウスを離す位置を指定
if(enter)
p2 = e.getPoint();
//最初に描く長方形のサイズを決める
r1.setSize(Math.abs(e.getX() - r1.x), Math.abs(e.getY() - r1.y));
repaint();
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseMoved(MouseEvent e){}
}
No.3ベストアンサー
- 回答日時:
まずpaint()メソッドの中で表示と操作が混ざってしまっているのが問題ですね。
paint()メソッドはウィンドウが重なってて上になった時などその瞬間の表示を
するために呼び出されます。
したがって表示のみを行います。現在のr1の表示、drawRectだけすればいいわけです。
そしてマウスのイベントのところでr1を変更し、最後にrepaint()すれば四角の表示が
更新されていきます。r1を変更することが操作になるわけです。
今回は(1)「新規に四角を書く」という操作と(2)「既存の四角を移動させる」という操作があります。
ユーザの操作としてはmousePressedのタイミングで(1)か(2)が決まりますのでフラグ変数を
セットしてmouseDraggedやmouseReleasedで条件分岐するとわかりやすいでしょう。
四角形の移動ですが、座標Aでボタンを押し座標Bをとおって座標Cと移動させたとき、座標ABの
差分が移動量になります。Rectangleクラスのtranslate()メソッドを使うと
Rectangleオブジェクトに対して移動量を指定することができます。
そして次回のために座標Bを示すp2をp1にコピーし、次回の始点としておきます。
次に座標Cに移動したときには座標BCの差分を求めますので座標Cをp2とすればまた移動量が
求められます。
蛇足ですが移動かどうかを判断するメソッドを作ってすっきりさせることもできます。
たとえばこんな感じ。(操作の違いを色で分かるようにしてみました)
元のプログラムを利用していますので、新規に描画する際、マウスを左上にドラッグすると
右下に大きくなるのは次の課題ですかね(^^;
public class RectFrame <略>{
//移動として操作中かどうか
boolean isDragged = false;
//長方形
Rectangle r1 = new Rectangle(0,0,0,0);
//Shiftキーを押したまま、マウスを押した位置と離した位置
Point p1;
Point p2;
//確認用の色指定
Color col;
public void init(){
addMouseListener(this);
addMouseMotionListener(this);
col = Color.black; //既定値を黒
}
public void paint(Graphics g){
//表示処理のみ行う
g.setColor(col);
g.drawRect(r1.x, r1.y, r1.width, r1.height);
}
//移動操作かどうかの判定用メソッド
private boolean isDraggMode(MouseEvent e){
return ((e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) ==
MouseEvent.SHIFT_DOWN_MASK) && r1.contains(e.getPoint());
}
public void mousePressed(MouseEvent e){
//マウスが長方形の内部に入っているかどうか
if(isDraggMode(e)){
//p1はマウスを押した位置, p2はnull
p1 = e.getPoint();
p2 = null;
isDragged = true;
col = Color.red;
}else{
r1.setLocation(e.getPoint());
r1.setSize(0,0);
col = Color.green;
}
repaint();
}
public void mouseDragged(MouseEvent e){
//マウスの位置
p2 = e.getPoint();
if(isDragged){
r1.translate((p2.x - p1.x),(p2.y - p1.y));
p1 = p2;//次回はこれが始点になる
}else{
//最初に描く長方形のサイズを決める
r1.setSize(Math.abs(e.getX() - r1.x), Math.abs(e.getY() - r1.y));
}
repaint();
}
public void mouseReleased(MouseEvent e){
//マウスを離す位置を指定
p2 = e.getPoint();
if(isDragged){
isDragged = false;
r1.translate((p2.x - p1.x),(p2.y - p1.y));
p1 = null;
p2 = null;
}else{
//最初に描く長方形のサイズを決める
r1.setSize(Math.abs(p2.x - r1.x), Math.abs(p2.y - r1.y));
}
col = Color.black;
repaint();
}
<マウスリスナのメソッド略>
}
うまくいきました。分かりやすい説明をありがとうございました。
paintは表示のみを行うこと、移動にtranslateを使うこと、などがよく分かりました。
No.2
- 回答日時:
ぱっと見ただけですが
プロパティ isS と enter は両方あわせて moving とでもすべきでは?
プロパティ drawing も必要では?
メソッド paint はシステム都合で呼ばれるので、プロパティ r1 を更新してはいけない
メソッド mousePressed にてプロパティ r1 の初期化は drawing 時だけ
メソッド mouseDragged にてプロパティ r1 の変更は drawing 時だけ
メソッド mouseReleased の処理で moving や drawing を初期化
isSとenterを合わせること、paintでのr1の更新をしない、といった変更を加えたところ、ある程度改善しました。ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 物理学 この問題における抵抗r1とxってどのように考えれば良いのでしょうか?トルクはT=P2/ωsなのでP2 1 2022/06/19 18:46
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- Visual Basic(VBA) VBAで最新のデータを別シートに転記する方法をお教えください。 3 2022/04/07 19:20
- Excel(エクセル) エクセルで書式設定とフィルタの組み合わせでうまく行かないのですが 4 2022/10/07 10:02
- Visual Basic(VBA) 2つのシートの任意のセルの番号が一致したら、一致した行をコピーする VBA 2 2023/06/19 20:48
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- レトロゲーム テレビゲームICOで手を繋いでもすぐに離れてしまうことに関して 1 2022/08/07 21:37
- 工学 整合回路の基本で最大電力が供給できない・・・ 10 2023/03/31 00:43
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C#で、あるクラスのメンバーす...
-
Junitテストでvoid戻り値メッソ...
-
長方形を描いて、それを移動さ...
-
C#で別のFormへ複数の値を返そ...
-
Exception in thread "main" ...
-
JavaFXでの表内のチェックボッ...
-
配列の受け渡し
-
コンボボックスを使う時の警告
-
Processingでマウスクリックで...
-
ArrayListを使ったJavaコンパイ...
-
ボタンの複数割り当てについて
-
ボタンのイベントで異なるウィ...
-
【Java】画像表示が出来ない!
-
JPanel上のマウスの座標の取得
-
フェードアウト時にぶちっと画...
-
GetDIBits関数の使い方について
-
C# MouseHoverを何度も呼ぶには
-
webブラウザの戻る・進むボタン
-
大量のデータを読み込んで表示...
-
決められて時間が経過するとア...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
大量のデータを読み込んで表示...
-
C#で、あるクラスのメンバーす...
-
Junitテストでvoid戻り値メッソ...
-
C#でのWNetAddConnection3の使...
-
Processingでマウスクリックで...
-
ボタンの複数割り当てについて
-
エンターキーを押すとOKボタン...
-
C# 矢印キーの取得
-
C# visibleプロパティをfalseに...
-
Thread.sleepのInterruptedExce...
-
C# DataGridView列カスタマイズ
-
C#でキーイベントが発生しない...
-
LVM_SETITEMSTATEでListViewの...
-
[C#.net]スレッド化された別フ...
-
GetDIBits関数の使い方について
-
C# 半角カナの文字化けについて
-
C# 親フォームで指定した値を...
-
javaアプレット repaintのタイ...
-
デスクトップマスコットのドラ...
-
C#で別のFormへ複数の値を返そ...
おすすめ情報