- PR -

Appletでマウスの座標の取得について

1
投稿者投稿内容
Sin
会議室デビュー日: 2003/11/05
投稿数: 9
投稿日時: 2003-11-05 09:36
はじめまして。最近、Appletを始めました。色々とわからないところがあり、
教えていただきたく思います。

現在、Canvasに画像を表示し、その画像をマウスでクリックした座標を
取得したいと思っております。そこでマウスイベントを取得して
ダイアログで座標を表示させているのですが、座標の取り方がおかしくてで
上手くいきません。
あと、ある範囲の座標をクリックしたらCanvasの画像を切り替えたりしてみたいの
ですが、どのように行ったらよいのかよくわかりません。

下に記述しているプログラムの一部を記述しましたので、おかしい点がありましたら
ご指摘よろしくお願いします。Canvasのメソッドは、長くなってしまうため
書いていません。
よろしくお願いいたします。


public class scroll_img extends Applet implements MouseListener{

public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mousePressed(MouseEvent e){
Frame dummy = new Frame();
msgDialog d = new msgDialog(dummy,e);
d.setVisible(true);
}
public void mouseReleased(MouseEvent e){}
public void mouseExited(MouseEvent e){}

class msgDialog extends Dialog implements ActionListener {
Button closeButton;
msgDialog(Frame f,MouseEvent e) {
super(f,"メッセージダイアログ",true);
add("North", new Label("getX()=" + e.getX()));
add("Center", new Label("getY()=" + e.getY()));
closeButton = new Button("Close");
closeButton.addActionListener(this);
add("South", closeButton);
pack();
}

public void actionPerformed( ActionEvent e){
dispose();
}
}
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-11-05 10:56
引用:

現在、Canvasに画像を表示し、その画像をマウスでクリックした座標を
取得したいと思っております。そこでマウスイベントを取得して
ダイアログで座標を表示させているのですが、座標の取り方がおかしくてで
上手くいきません。


MouseListenerをどこに登録しているのか分からないですが、取得できる座標は登録したコンポーネントのローカル座標(コンポーネントの左上を原点とした座標)だったような気がします。Appletの位置を動かしても、同じ所をクリックしていれば、取得される座標は同じになりますよ。

引用:

ある範囲の座標をクリックしたらCanvasの画像を切り替えたりしてみたいの
ですが、どのように行ったらよいのかよくわかりません。


複数枚の画像(Canvas)をループさせる(切り替えるの)であれば、CardLayoutが使えるでしょう。
使用方法は、WEBで検索かければ、たぶん見つかることでしょう。
切り替えのトリガーはMouseListener#mouseClicked()でクリックした座標を監視すれば良いでしょう。もちろんこの時の座標もローカル座標で返ってきますよ。

AppletはWEB Browserから用意された、Frameに張りつけているはずなので、わざわざダミーでフレーム作らなくても、親コンポーネントをたどっていけば、Frameにたどり着くと思います。やり方の詳細は、JOptionPane#getWindowForComponent()のソースコードが参考になると思います。
# mouse clickの度にFrameとDialog作るのを見て目が丸くなってしまった (@_@)

最近、Appletに触っていないので、あまり当てにならないかもしれません。
Sin
会議室デビュー日: 2003/11/05
投稿数: 9
投稿日時: 2003-11-05 12:22
かずくんさんありがとうございます。

>取得できる座標は登録したコンポーネントのローカル座標(コンポーネントの左上を原点と
>した座標)だったような気がします。Appletの位置を動かしても、同じ所をクリックして
>いれば、取得される座標は同じになりますよ。

その通りでした。ローカルの座標を取っていました。
例えば、Canvasに貼ってある画像をスクロールバーで動かしたときその画像の
座標って取得できないのでしょうか?

>複数枚の画像(Canvas)をループさせる(切り替えるの)であれば、CardLayoutが使えるでしょう。

CardLayoutは使った事がなかったので、現在調べていますが、できそうな感じです 。

>JOptionPane#getWindowForComponent()のソースコードが参考になると思います。

getWindowForComponent()メソッドなのですが、Webで検索すると日本語ページって
ないですよね??これってどのようなメソッドなのですか??

よろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-11-05 13:18
unibon です。こんにちわ。

引用:

Sinさんの書き込み (2003-11-05 12:22) より:
その通りでした。ローカルの座標を取っていました。
例えば、Canvasに貼ってある画像をスクロールバーで動かしたときその画像の
座標って取得できないのでしょうか?


Swing になりますが、SwingUtilities クラスの convertPoint メソッドが使えます。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/javax/swing/SwingUtilities.html#convertPoint(java.awt.Component,%20java.awt.Point,%20java.awt.Component)
なお、もしもアプレットを JDK 1.1 相当の環境で動かされたい場合は、このメソッドは使えませんが、
後述のように JDK に付属のソースコードを見ることはできますので、
動作原理の参考にはできます。

引用:

Sinさんの書き込み (2003-11-05 12:22) より:
>JOptionPane#getWindowForComponent()のソースコードが参考になると思います。

getWindowForComponent()メソッドなのですが、Webで検索すると日本語ページって
ないですよね??これってどのようなメソッドなのですか??


このメソッドはアクセス修飾がデフォルト(package)なので、日本語の解説はないです。
そもそも英語でも API リファレンスには載っていません。
ソースコードは JDK に付属する src.zip などを展開すれば見ることができます。
Sin
会議室デビュー日: 2003/11/05
投稿数: 9
投稿日時: 2003-11-05 16:06
unibonさん返答ありがとうございます。

引用:
Swing になりますが、SwingUtilities クラスの convertPoint メソッドが使えます。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/javax/swing/SwingUtilities.html#convertPoint(java.awt.Component,%20java.awt.Point,%20java.awt.Component)



convertPointでできそうなのですが、もう少し質問させてください。
認識違いしている可能性があるので。。。

public static Point convertPoint(Component source,
Point aPoint,
Component destination)
ですよね?この引数のsourceとdestinationの部分がよくわからないのですが、
sourceは、Canvasに貼ってある画像でdestinationは、画像全体を
指定すればよいのかと思ったのですが、destinationは、Componentなので
Image型の変数は、使用できませんよね?Panelに貼り付けようとしても
Panel pane = new Panel();
pane.add(img);
としてみたのですが、エラーになってしまいます。
画像全体をComponent型にするにはどうすればよいのでしょうか?

すみません。わかりにくい質問になってしまいました。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-11-05 20:37
unibon です。こんにちわ。

引用:

Sinさんの書き込み (2003-11-05 16:06) より:
public static Point convertPoint(Component source,
Point aPoint,
Component destination)
ですよね?この引数のsourceとdestinationの部分がよくわからないのですが、
sourceは、Canvasに貼ってある画像でdestinationは、画像全体を
指定すればよいのかと思ったのですが、destinationは、Componentなので
Image型の変数は、使用できませんよね?Panelに貼り付けようとしても


現在は Image をどうやって表示していて、
どのようにスクロールされようと目論まれているのでしょうか。
提示されたコードからはそのへんがあまり良く見えません。
Image は Component ではないので、Image を表示しようとすれば、
Component の paint メソッドで drawImage するか、
あるいは、Swing なら JLabel と ImageIcon を組み合わせるなどの
簡易的な描画方法もありますが。

ちなみに convertPoint メソッドは ScrollPane/JScrollPane など、
Container に Component を入れた構成の場合には役に立ちますが、
入れ子になっていないような構成の場合には使えません。
Sin
会議室デビュー日: 2003/11/05
投稿数: 9
投稿日時: 2003-11-05 22:08
unibonさん本当にありがとうございます。
今、作成しているプログラムです。
お手数ですが、おかしい箇所などを指摘していただけると
嬉しく思います。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class testimg extends Applet implements MouseListener{

int image_width = 893;
int image_height = 738;

Scrollbar horz_sb = new Scrollbar(Scrollbar.HORIZONTAL);
Scrollbar vert_sb = new Scrollbar(Scrollbar.VERTICAL);
ImgCanvas image_canvas;
Image img;

public void init() {
img = getImage(getCodeBase(),"test.jpg");
image_canvas = new ImgCanvas(img);
image_canvas.addMouseListener(this);
setLayout(new BorderLayout());
add("South", horz_sb);
add("East", vert_sb);
add("Center", image_canvas);
}

public void start() {
Dimension canvas_size = image_canvas.getSize();
horz_sb.setValues(0, canvas_size.width, 0, image_width);
vert_sb.setValues(0, canvas_size.height, 0, image_height);
}

public boolean handleEvent(Event evt) {
if ((evt.target == vert_sb) || (evt.target == horz_sb)) {
image_canvas.set_image_offset(-horz_sb.getValue(),-vert_sb.getValue());
return true;
}
return false;
}
}

public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mousePressed(MouseEvent e){
Point pointX = e.getPoint();
Point point = SwingUtilities.convertPoint(image_canvas,pointX,image_canvas1);
}
public void mouseReleased(MouseEvent e){}
public void mouseExited(MouseEvent e){}
}

class ImgCanvas extends Canvas {
Image canvas_image;
int x_offset, y_offset;

public ImgCanvas(Image img) {
super();
canvas_image = img;
x_offset = y_offset = 0;
}

public void set_image_offset(int x, int y){
x_offset = x;
y_offset = y;
repaint();
}

public void paint(Graphics g) {
g.drawImage(canvas_image, x_offset, y_offset, this);
}
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-11-05 23:08
unibon です。こんにちわ。

自前で、Scrollbar の値から Canvas のスクロール量を決定しているので、
mousePressed の位置の補正も逆の手順でやるだけで良いと思います。
以下、それを追加した例です。

コード:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
// import javax.swing.*;

public class testimg extends Applet implements MouseListener {

    int image_width = 893;
    int image_height = 738;

    Scrollbar horz_sb = new Scrollbar(Scrollbar.HORIZONTAL);
    Scrollbar vert_sb = new Scrollbar(Scrollbar.VERTICAL);
    ImgCanvas image_canvas;
    Image img;

    public void init() {
        img = getImage(getCodeBase(), "test.jpg");
        image_canvas = new ImgCanvas(img);
        image_canvas.addMouseListener(this);
        setLayout(new BorderLayout());
        add("South", horz_sb);
        add("East", vert_sb);
        add("Center", image_canvas);
    }

    public void start() {
        Dimension canvas_size = image_canvas.getSize();
        horz_sb.setValues(0, canvas_size.width, 0, image_width);
        vert_sb.setValues(0, canvas_size.height, 0, image_height);
    }

    public boolean handleEvent(Event evt) {
        if ((evt.target == vert_sb) || (evt.target == horz_sb)) {
            image_canvas.set_image_offset(-horz_sb.getValue(), -vert_sb.getValue());
            return true;
        }
        return false;
    }

    public void mouseClicked(MouseEvent e) {
    }
    public void mouseEntered(MouseEvent e) {
    }
    public void mousePressed(MouseEvent e) {
        Point pointX = e.getPoint();
        // Point point = SwingUtilities.convertPoint(image_canvas, pointX, image_canvas);
        Point point = new Point(pointX.x - image_canvas.x_offset, pointX.y - image_canvas.y_offset);
        System.out.println("point = " + point);
    }
    public void mouseReleased(MouseEvent e) {
    }
    public void mouseExited(MouseEvent e) {
    }
}

class ImgCanvas extends Canvas {
    Image canvas_image;
    int x_offset, y_offset;

    public ImgCanvas(Image img) {
        super();
        canvas_image = img;
        x_offset = y_offset = 0;
    }

    public void set_image_offset(int x, int y) {
        x_offset = x;
        y_offset = y;
        repaint();
    }

    public void paint(Graphics g) {
        g.drawImage(canvas_image, x_offset, y_offset, this);
    }
}


ただ、画に縦・横のスクロールバーを備えるならば、
通常は ScrollPane を使ったほうが標準的なユーザインターフェースなので良いです。
その場合は mousePressed の引数 MouseEvent の値が、
そのまま求める座標として得られますので、別段 convertPoint も不要です。
convertPoint は、逆に、スクロールする Canvas のスクロール量を無視して
フレームを基準とした座標を得たいような感じの場面で使ったりします。
1

スキルアップ/キャリアアップ(JOB@IT)