【问题标题】:Swing: Creating a draggable component...?Swing:创建一个可拖动的组件...?
【发布时间】:2010-10-26 20:07:24
【问题描述】:

我在网上搜索了可拖动 Swing 组件的示例, 但我发现了不完整或无效的示例。

我需要的是一个可以被鼠标拖动Swing组件 在另一个组件内。在被拖动时,它应该已经 改变它的位置,而不仅仅是“跳”到它的目的地。

我希望能在没有非标准 API 的情况下工作的示例。

谢谢。

【问题讨论】:

    标签: java swing drag-and-drop draggable


    【解决方案1】:

    我提出了一个简单但运行良好的解决方案,我自己发现了;)

    我该怎么办?

    • 按下鼠标时,我记录光标的位置在屏幕上,然后 组件的位置。
    • 当鼠标被拖动时,我计算新和之间的 差异 旧的光标位置在屏幕上,然后移动 组件通过这种差异

    在 Linux(OpenSuse、KDE3)下使用最新的 JDK 6 进行测试,
    但是,嘿,它是 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);
      }
    
    }
    

    【讨论】:

    • 如果您使用MouseAdapterMouseMotionAdapter 代替侦听器,则无需覆盖这些额外的方法。
    【解决方案2】:

    另外,我发现可以在 JFrame 中创建 JInternalFrame, 但问题是:你总是得到一个烦人的窗口标题栏

    遗憾的是,要禁用标题栏,需要一个肮脏的解决方法

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

    我真的很怀念像“someInternalFrame.setWindowTitleBar(false)”这样的方法...
    :'(

    【讨论】:

    • 子类化可以提供setWindowTitleBar()方法!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多