2009-05-17 14 views
16

Tôi đã tìm kiếm trên web ví dụ về các thành phần Swing có thể kéo, nhưng tôi đã tìm thấy ví dụ không hoàn chỉnh hoặc không hoạt động.Swing: Tạo thành phần có thể kéo được ...?

Những gì tôi cần là một thành phần Swing có thể được kéo bởi chuột bên trong một thành phần khác. Trong khi bị kéo, cần đã thay đổi vị trí của nó, không chỉ 'nhảy' đến đích của nó.

Tôi sẽ đánh giá cao các ví dụ hoạt động không có API không chuẩn.

Cảm ơn bạn.

Trả lời

29

Tôi đề xuất một giải pháp đơn giản nhưng hiệu quả, được phát hiện một mình;)

Tôi phải làm gì?

  • Khi chuột được nhấn, tôi ghi lại vị trí con trỏ của trên màn hình và vị trí thành phần của.
  • Khi chuột được kéo, tôi tính toán chênh lệch giữa mới và cũ con trỏ của vị trí trên màn hình , và di chuyển phần bởi sự khác biệt này.

Tested với JDK mới nhất 6 unter Linux (OpenSuse, KDE3),
nhưng hey, nó là Java Swing, nên làm việc như nhau ở khắp mọi nơi.

Ở đây đi mã:

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); 
    } 

} 
+0

tôi hoạt động hoàn hảo và súc tích. Cảm ơn vì đã cứu tôi. – Dhanushka

1

Ngoài ra, tôi phát hiện ra rằng người ta có thể tạo ra một JInternalFrame bên trong một JFrame, nhưng vấn đề là: bạn nhận được luôn là một khó chịu tiêu đề cửa sổ thanh.

Để vô hiệu hóa thanh tiêu đề, thật đáng buồn, một bẩn workaround là cần thiết:

public class MyDraggableComponent extends JInternalFrame { 

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

} 

Tôi thực sự nhớ một phương pháp như "someInternalFrame.setWindowTitleBar (false)" ...
: '(

+2

Phân lớp có thể cung cấp phương thức 'setWindowTitleBar()'! – 11684

1

Dưới đây là một cách tiếp cận khác mà bạn có thể muốn thử.Tôi nghĩ rằng nó khá sạch sẽ.Chỉ cần sao chép các lớp sau và sử dụng nó như thế này:

Cách sử dụng:

DragListener dl = new DragListener(componentOrWindowToBeMoved); dl.addHandle(componentToPickWithTheMouse);

Class:

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); 
    } 
}