Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Коды клавиш

Ввод символов
Аплеты JDK 1.1 и клавиатура
Аплет JDK 1.0 и клавиатура
Мышь в JDK 1.1
Перемещение объектов
Аплет JDK 1.0 и мышь
Регулируем размер изображения
Автономное приложение и мышь

Назад Вперед

4.6. Перемещение объектов мышью

Пример демонстрирует способы обработки событий от мыши в модели JDK версии 1.1. Рассказано о применении методов интерфейса MouseMotionListener.

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Демонстрация
(ваш браузер должен уметь работать с аплетами Java в стандарте JDK 1.1)

Немного теории

Как мы уже говорили в описании предыдущего примера, для обработки событий от мыши в JDK 1.1 предусмотрены два интерфейса - MouseListener и MouseMotionListener. Там же мы подробно рассмотрели интерфейс MouseListener.

Теперь мы на конкретном примере расскажем об использовании интерфейса MouseMotionListener. Этот интерфейс предназначен для отслеживания перемещения курсора мыши. Его регистрация выполняется при помощи метода addMouseMotionListener.

Интерфейс MouseMotionListener предполагает реализацию следующих методов:

Метод Действие пользователя, в результате которого метод получает управление
mouseMoved Перемещение курсора мыши
mouseDraged Операция переноса объектов: пользователь нажимает клавишу мыши, перемещает курсор и затем отпускает клавишу мыши

В процессе перемещения курсора или перетягивания объекта методы вызываются многократно.

В качестве единственного параметра указанным методам передается ссылка на объект класса MouseEvent, например:

public void mouseMoved(MouseEvent e)
{
}

Из предыдущих разделов нашей библиотеки примеров вы уже знаете, что при помощи этой ссылки приложение Java может извлечь разнообразную информацию о мыши на момент возникновения события.

Внутри методов mouseMoved и mouseDraged приложения обычно вызывают методы getX и getY возвращающие координаты курсора мыши. При необходимости воспользуйтесь методом getPoint. Он возвращает ссылку на объект класса Point, содержащий текущие координаты мыши.

Описание примера

Внутри окна нашего аплета имеется небольшое изображение дискеты, которое можно перемещать при помощи мыши (рис. 1).

pic1.gif (1998 bytes)

Рис. 1. Окно аплета с изображением дискеты

В процессе перемещения аплет контролирует выход дискеты за границы окна, отмеченные тонкой рамкой черного цвета.

Как устроен наш аплет?

Класс MouseMove

Главный класс нашего аплета MouseMove реализует сразу два интерфейса - MouseMotionListener и MouseListener:

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class MouseMove extends Applet 
  implements MouseMotionListener, MouseListener
{
  . . .
}

При помощи первого из них мы отслеживаем изменение координат курсора мыши при выполнении операции перемещения дискеты, а второй нужен нам для определения координат этого курсора в начале перемещения.

Расскажем о полях класса MouseMove.

В поле imFloppy записана ссылка на изображение дискеты:

Image imFloppy;

Поля imHeight и imWidth хранят размеры этого изображения в пикселах по вертикали и горизонтали, соответственно:

int imHeight;
int imWidth;

В поле rcImage хранятся текущие границы области, занимаемой изображением дискеты в окне аплета:

Rectangle rcImage;

Флаг bBeginDrag принимает значение true на время выполнения операции перемещения изображения дискеты:

boolean bBeginDrag = false;

Поля imX и imY хранят текущие координаты курсора мыши при перемещении изображения дискеты:

int imX = 0;
int imY = 0;

Когда пользователь начинает перемещение дискеты, он располагает курсор в произвольное место изображения и начинает перемещение. В переменных dx и dy мы храним смещение точки "захвата" изображения дискеты относительно верхнего левого угла этого изображения:

int dx = 0;
int dy = 0;

Заметим, что это смещение имеет отрицательный знак.

И, наконец, в поле dm хранятся текущие размеры окна аплета:

Dimension dm;

Метод init

При инициализации мы загружаем изображение дискеты из файла disk.gif. Предполагается, что этот файл находится в том же каталоге, что и файл байт-кода аплета.

Однако загрузка файла через медленные каналы Internet может занять некоторое время, поэтому мы выполняем ожидание завершения  процесса при помощи специально предназначенного для этого класса MediaTracker:

MediaTracker tr = new MediaTracker(this);
    
imFloppy = getImage(getCodeBase(),
  "disk.gif");
tr.addImage(imFloppy, 0);
try
{
  tr.waitForAll();
}
catch (InterruptedException e) {}

Когда загрузка будет завершена, метод init определяет размеры изображения дискеты и сохраняет их в соответствующих полях:

imHeight = imFloppy.getHeight(this);
imWidth = imFloppy.getWidth(this);

Далее инициализируется поле rcImage, содержащее границы области, занимаемой изображением:

rcImage = new Rectangle(imX, imY, 
  imHeight, imWidth);

Мы также определяем и сохраняем размеры окна аплета:

dm = getSize();

На завершающей стадии своей работы метод init регистрирует интерфейсы MouseMotionListener и MouseListener:

this.addMouseMotionListener(this);
this.addMouseListener(this);

Метод paint

Этот метод обводит границы аплета тонкой рамкой, рисует изображение дискеты в текущей позиции и обновляет соответствующим образом переменную rcImage:

public void paint(Graphics g)
{
  g.drawRect(0, 0, 
    dm.width - 1, dm.height - 1);
      
  g.drawImage(imFloppy, 
    imX + dx, imY + dy, this);
    
  rcImage = new Rectangle(imX + dx, imY + dy, 
    imHeight, imWidth);
}

Заметим, что к текущим координатам курсора мыши (imX, imY) мы прибавляем смещение курсора внутри изображения (dx, dy).

Метод mousePressed

Когда пользователь нажимает клавишу мыши в окне аплета, управление передается методу mousePressed:

public void mousePressed(MouseEvent e)
{
  bBeginDrag = 
    rcImage.contains(e.getX(), e.getY());
      
  if(bBeginDrag)
  {
    dx = imX + dx - e.getX();
    dy = imY + dy - e.getY();
  }  
}

Вначале с помощью метода contains класса Rectangle этот метод проверяет, находится ли курсор мыши над изображением дискеты. Если находится, то в поле bBeginDrag (признак начала операции перемещения) записывается значение true.

Кроме того, при этом метод mousePressed определяет новое смещение курсора относительно верхнего левого угла изображения.

Метод mouseReleased

Когда операция перемещения завершается, пользователь отпускает кнопку мыши. Мы при этом сбрасываем флаг перемещения bBeginDrag:

public void mouseReleased(MouseEvent e)
{
  bBeginDrag = false;
}

Метод mouseDragged

В процессе перемещения изображения дискеты управление многократно передается методу mouseDragged.

При установленном флаге bBeginDrag он определяет новые координаты курсора мыши и записывает их в переменные newX и newY:

int newX;
int newY;
    
if(bBeginDrag)
{
  newX = e.getX();
  newY = e.getY();
  . . .
}

Далее мы проверяем, не выходит ли изображение дискеты за пределы окна аплета, ограниченные тонкой рамкой.

Вот как эта операция выполняется для оси X:

if(newX < -dx)
  imX = -dx;
        
else if((newX + imWidth + dx) > dm.width)
  imX = dm.width - imWidth - dx;
        
else
  imX = newX;

Аналогично, для оси Y:

if(newY  < -dy)
  imY = -dy;
        
else if((newY + imHeight + dy) > dm.height)
  imY = dm.height - imHeight - dy;
        
else
  imY = newY;

Затем метод перерисовывает окно аплета:

repaint();

Остальные методы

следующие четыре метода определены для полноты реализации интерфейсов MouseListener и MouseMotionListener:

public void mouseMoved(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}

Назад Вперед

[Назад]