Вам нужно добавить MouseMotionListener
и реализовать mouseMoved()
или mouseDragged()
, если хотите.
Есть несколько способов, как вы могли бы сделать это. Это зависит от того, хотите ли вы щелкнуть-переместить или перетащить. Разница:
- click-move: нажмите, отпустите, переместите, нажмите, отпустите
- перетаскивание: нажмите, переместите, отпустите
Click-ход
В этом случае вам нужно реализовать
- Обработчик
mouseClicked()
наблюдателя MouseListener
для переключения boolean
и запоминания начальной позиции движения.
-
mouseMoved()
наблюдателя MouseMotionListener
для выполнения фактического движения.
Как это:
class Mover implements MouseListener, MouseMotionListener {
private boolean moving;
private Point movementOrigin;
public void mouseClicked(MouseEvent e) {
if (moving = !moving)
movementOrigin = e.getPoint();
}
public void mouseMoved(MouseEvent e) {
if (!moving) return;
Point pos = e.getPoint();
Point delta = new Point(pos.getX() - movementOrigin.getX(), pos.getY() - movementOrigin.getY());
// TODO Relocate the circle with that delta
repaint();
}
}
Drag
В этом случае вам нужно реализовать
* Обработчик mousePressed()
наблюдателя MouseListener
для начальной позиции перетаскивания.
* Обработчик mouseDragged()
наблюдателя MouseMotionListener
для отслеживания перетаскивания.
Единственное отличие от предыдущего кода в том, что вам не нужен этот логический переключатель.
Примечание об оригинальном ответе
В своем первоначальном ответе я предложил динамически добавлять / удалять MouseMotionListener
в соответствующем событии MouseListener
. Я больше не думаю, что это хорошая идея, потому что не существует «дешевого» способа определить, был ли уже зарегистрирован наблюдатель, и, таким образом, в любом случае понадобится логическое значение.
Примечание о коде
Я не думаю, что хорошо иметь поле типа Graphics2D
, инициализированное методом paint()
. Действительность экранного объекта Graphics
, вероятно, связана с деревом вызовов repaint()
. Вызов его методов вне дерева вызовов repaint()
, вероятно, приведет к неопределенному поведению. Время жизни объекта Graphics
- это дерево вызовов repaint()
, а не объект ExampleGUI
, и код должен отражать это, не кэшируя его в поле.
Расширение классов пользовательского интерфейса (ваш extends JFrame
) для использования является анти-паттерном и нарушает принцип подстановки Лискова. Наследование (все еще) чрезмерно используется. Попробуйте использовать делегирование вместо наследования.