Swing: создание перетаскиваемого компонента...?
Я искал в Интернете примеры перетаскиваемых компонентов Swing,
но я нашел либо неполные, либо неработающие примеры.
Мне нужен компонент Swing, который можно перетащить с помощью мыши
внутри другого компонента. При перетаскивании он должен уже
измените его позицию, а не просто "перейдите" к месту назначения.
Я был бы признателен за примеры, которые работают без нестандартных API.
Спасибо.
Ответы
Ответ 1
Я предлагаю простое, но хорошо работающее решение, обнаруженное мною;)
Что мне делать?
- Когда мышь нажата, я записываю < позицию курсора на экране и
положение компонента.
- Когда мышь перетаскивается, я вычисляю разницу между новыми и
старой курсор позиция на экране и переместите
компонент с помощью этой разницы.
Протестировано с последним JDK 6 unter Linux (OpenSuse, KDE3),
но эй, это Java Swing, должен работать одинаково везде.
Вот код:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class MyDraggableComponent
extends JComponent {
private volatile int screenX = 0;
private volatile int screenY = 0;
private volatile int myX = 0;
private volatile int myY = 0;
public MyDraggableComponent() {
setBorder(new LineBorder(Color.BLUE, 3));
setBackground(Color.WHITE);
setBounds(0, 0, 100, 100);
setOpaque(false);
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) { }
@Override
public void mousePressed(MouseEvent e) {
screenX = e.getXOnScreen();
screenY = e.getYOnScreen();
myX = getX();
myY = getY();
}
@Override
public void mouseReleased(MouseEvent e) { }
@Override
public void mouseEntered(MouseEvent e) { }
@Override
public void mouseExited(MouseEvent e) { }
});
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
int deltaX = e.getXOnScreen() - screenX;
int deltaY = e.getYOnScreen() - screenY;
setLocation(myX + deltaX, myY + deltaY);
}
@Override
public void mouseMoved(MouseEvent e) { }
});
}
}
public class Main {
public static void main(String[] args) {
JFrame f = new JFrame("Swing Hello World");
// by doing this, we prevent Swing from resizing
// our nice component
f.setLayout(null);
MyDraggableComponent mc = new MyDraggableComponent();
f.add(mc);
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
}
}
Ответ 2
Кроме того, я обнаружил, что внутри JFrame можно создать JInternalFrame,
но проблема в том, что вы всегда получаете раздражающую строку заголовка окна.
Чтобы отключить строку заголовка, к сожалению, необходим обходной :
public class MyDraggableComponent extends JInternalFrame {
public MyDraggableComponent() {
InternalFrameUI thisUI = getUI();
if (thisUI instanceof BasicInternalFrameUI) {
((BasicInternalFrameUI) thisUI).setNorthPane(null);
}
}
Я действительно пропустил такой метод, как "someInternalFrame.setWindowTitleBar(false)"...
: '(
Ответ 3
Вот еще один подход, который вы можете попробовать. Я думаю, что он довольно чистый. Просто скопируйте следующий класс и используйте его следующим образом:
Использование:
DragListener dl = new DragListener(componentOrWindowToBeMoved);
dl.addHandle(componentToPickWithTheMouse);
Класс:
import java.awt.Component;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DragListener extends MouseAdapter {
private final Component COMPONENT_TO_DRAG;
private final int MOUSE_BUTTON;
private Point mousePosition;
private Point sourceLocation;
private Point locationOnScreen;
private int buttonPressed;
public DragListener(final Component componentToDrag) {
this(componentToDrag, MouseEvent.BUTTON1);
}
public DragListener(final Component componentToDrag, final int mouseButton) {
this.COMPONENT_TO_DRAG = componentToDrag;
this.MOUSE_BUTTON = mouseButton;
}
@Override
public void mousePressed(final MouseEvent e) {
this.buttonPressed = e.getButton();
this.mousePosition = MouseInfo.getPointerInfo().getLocation();
this.sourceLocation = new Point();
}
@Override
public void mouseDragged(final MouseEvent e) {
if (this.buttonPressed == MOUSE_BUTTON) {
this.locationOnScreen = e.getLocationOnScreen();
this.sourceLocation = this.COMPONENT_TO_DRAG.getLocation(this.sourceLocation);
this.sourceLocation.translate((int) (this.locationOnScreen.getX() - this.mousePosition.getX()), (int) (this.locationOnScreen.getY() - this.mousePosition.getY()));
this.COMPONENT_TO_DRAG.setLocation(this.sourceLocation);
this.mousePosition = MouseInfo.getPointerInfo().getLocation();
}
}
public void addHandle(Component handle) {
handle.addMouseListener(this);
handle.addMouseMotionListener(this);
}
}