【问题标题】:Implementing Drag and Drop using MouseListener for custom Components使用 MouseListener 为自定义组件实现拖放
【发布时间】:2010-04-01 10:14:13
【问题描述】:

我正在处理一项学校作业,该作业要求我能够拿起一块瓷砖,将其拖到某个位置,然后将其放在那里。我能够使用TransferHandler 和 dnd 包中的一堆东西来完成这项工作,但根据教授的说法,这不是为这项作业执行此操作的可接受方式。所以,我尝试使用MouseListener 接口来达到同样的效果。

基本设置是这样的:我有一个名为LocationViewJPanel 派生类,其中包含JLabel 派生的TileView 实例。我需要获取事件,这些事件为我提供按下鼠标的LocationView 和释放鼠标的LocationView。我正在通过TileView 将鼠标事件代理到它包含的LocationView,以便我可以正确处理mousePressed 事件。

我将System.out.println() 添加到mousePressedmouseReleased 的鼠标侦听器到LocationViewTileView,以便我可以观察正在生成的事件。令我惊讶的是,在位置 A 的图块 A 上按下鼠标,然后拖动到位置 B 并释放会为图块 A 和位置 A 生成鼠标释放事件,但不会为位置 B 生成鼠标释放事件。我只需要触发鼠标释放事件位置 B。

为了解决这个问题,我尝试根据http://weblogs.java.net/blog/2006/09/20/well-behaved-glasspane 中的FinalGlassPane 实现一个玻璃窗格。添加玻璃窗格并为其添加事件侦听器后,我可以看到鼠标事件确实是通过玻璃窗格过滤的,但鼠标释放事件仍然只在鼠标单击的项目上被调用。

有没有办法让mousePressedmouseReleased 事件关联到相同的拖动动作在不同的组件上被调用?

编辑: 这是我根据 lins314159 的回答得出的解决方案

public void mouseReleased(MouseEvent e) {
    Point p = SwingUtilities.convertPoint(LocationView.this, ((Component)e.getSource()).getLocation(), LocationView.this.wsa.getGameView());
    e.translatePoint((int) p.getX(), (int) p.getY());
    Component tile = SwingUtilities.getDeepestComponentAt(LocationView.this.wsa.getGameView(), e.getX(), e.getY());
}

【问题讨论】:

    标签: java swing


    【解决方案1】:

    虽然有可能让mouseReleased 提供释放鼠标的实际组件作为其来源,但这会带来更多麻烦。

    以下可用于识别鼠标被释放的组件。

    public void mouseReleased(MouseEvent evt) {
        Point p = ((Component) evt.getSource()).getLocation();
        evt.translatePoint((int) p.getX(), (int) p.getY());
        Component tile = f.getContentPane().getComponentAt(evt.getX(), evt.getY());
    }
    

    【讨论】:

    • 这个源位置的翻译在我的情况下似乎不起作用。当我单击一个图块时,我将源的位置设为 1,1,然后将其转换为我所在的图块。这意味着生成的坐标不正确,导致错误的组件已选中。
    • 我稍微调整了你的代码,终于让它工作了。由于我拥有的嵌套组件的数量,需要进行调整。该解决方案作为对原始问题的编辑发布。
    猜你喜欢
    • 1970-01-01
    • 2018-03-22
    • 2015-12-06
    • 1970-01-01
    • 2020-11-04
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    相关资源
    最近更新 更多