Swing: создание перетаскиваемого компонента ...? - PullRequest
19 голосов
/ 17 мая 2009

Я искал в Интернете примеры перетаскиваемых компонентов Swing, но я нашел неполные или нерабочие примеры.

Мне нужен компонент Swing , который можно перетащить мышью внутри другого компонента. При перетаскивании он должен уже изменить свою позицию, а не просто «прыгнуть» к месту назначения.

Буду признателен за примеры, которые работают без нестандартных API.

Спасибо.

Ответы [ 3 ]

32 голосов
/ 17 мая 2009

Я предлагаю простое, но хорошо работающее решение, обнаруженное мной самостоятельно;)

Что мне делать?

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

Протестировано с последней версией JDK 6 под 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 голосов
/ 03 ноября 2017

Вот еще один подход, который вы можете попробовать. Я думаю, что это довольно чисто. Просто скопируйте следующий класс и используйте его так:

Использование:

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);
    }
}
1 голос
/ 18 мая 2009

Кроме того, я обнаружил, что можно создать JInternalFrame внутри JFrame, но проблема в том, что вы всегда получаете раздражающую строку заголовка окна .

Чтобы отключить строку заголовка, к сожалению, грязный обходной путь необходим:

public class MyDraggableComponent extends JInternalFrame {

  public MyDraggableComponent() {
    InternalFrameUI thisUI = getUI();
    if (thisUI instanceof BasicInternalFrameUI) {
      ((BasicInternalFrameUI) thisUI).setNorthPane(null);
    }

}

Мне действительно не хватает метода, подобного "someInternalFrame.setWindowTitleBar (false)" ...
: '(

...