Java 麻将游戏 - 帮助实现手牌重组,将 JLabel 移离我拖动所选棋子的位置

Java Mahjong Game - Help Implementing a hand reorganizing that shifts JLabels away from where I drag my chosen piece

我目前正在制作 java 麻将游戏,并且正在开发 GUI。我有一个 JPanel,它包含一个 JLabel 数组,每个 JLabel 都有一个自定义鼠标侦听器。

我想要的是实现某种重组手的方法。例如,你刚刚画了一个牌,你想把它放在最左边,以保持你手中的一些组织。

我已经可以拖动图块了,但我希望它在您松开时卡入到位,然后向下移动每个图块.所以如果我把它放在最左边,每个瓷砖都会向右移动一个。因此,该程序需要某种方式来 识别一个图块已被移动,并确定它所处的位置。 如果能提供有关如何实现此功能或我需要什么的指导,我将不胜感激至 change/add/research.

这是我的鼠标侦听器 class,如果需要任何其他信息,请告诉我。

package mahjongCode;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class DragAndDropListener extends MouseAdapter{
    private Point startPoint;
    private Component draggedObject;
    private JPanel panel;
    private JLabel[] handTiles;

    public DragAndDropListener(JPanel panel, JLabel[] handTiles){
        this.panel = panel;
        this.handTiles = handTiles;
    }
    @Override
    public void mousePressed(MouseEvent e){
        panel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        draggedObject = (Component) e.getSource();
        startPoint = SwingUtilities.convertPoint(draggedObject, e.getPoint(), 
                                                    draggedObject.getParent());
    }

    @Override
    public void mouseDragged(MouseEvent e){
        Point location = SwingUtilities.convertPoint(draggedObject, e.getPoint(), 
                                                        draggedObject.getParent());
        Point locTrans = location.getLocation();
        locTrans.translate(draggedObject.getParent().getX(), draggedObject.getParent().getY());
        if(draggedObject.getParent().getBounds().contains(locTrans)){
            Point newLocation = draggedObject.getLocation();
            newLocation.translate(location.x - startPoint.x, location.y - startPoint.y);
            newLocation.x = Math.max(newLocation.x, 0);
            newLocation.x = Math.min(newLocation.x, draggedObject.getParent().getWidth() - draggedObject.getWidth());
            newLocation.y = Math.max(newLocation.y, 0);
            newLocation.y = Math.min(newLocation.y, draggedObject.getParent().getHeight() - draggedObject.getHeight());
            draggedObject.setLocation(newLocation);
            panel.repaint();
            startPoint = location;
        }
    }

    @Override 
    public void mouseReleased(MouseEvent e){
        panel.setCursor(null);
        startPoint = null;
        draggedObject = null;
    }

    public void makeDraggable(Component component){
        component.addMouseListener(this);
        component.addMouseMotionListener(this);
    }

}

由于您有一个 JLabel 数组,您的解决方案已经完成了一半!我实际上最近才回答了 similar question

您可能会发现它很有用。

至于'snapping into place',如果您是根据数组索引绘制方块的手,则吸附会为您完成,因为它们会在吸附后绘制到位。

我对麻将知之甚少,但我认为麻将牌类似于 Uno 手中的牌,因为你不受固定值的限制。如果是这种情况,ArrayList 可能会非常有用。您可以在 ArrayList vs Array here 上阅读一些意见。


编辑:

我看到有几种方法可以解决这个问题,可能还有更多: 如果每个图块获得 frame/screen/pane 的相对部分,那么您可以获得它的 x 坐标值(图块上的红线),并且当您向左拖动鼠标(蓝色箭头,红点点)时,越过绿色箭头,自动将那个方块向左移动一个。

如果有一个最大的瓦片数量,比如4,在这个例子中,当你的鼠标移动超过一个固定的宽度时,你可以直接根据这个预定值交换瓦片。

也许我能看到的最简单的方法是:

获取鼠标释放拖放时(我假设是点击和拖动)最后已知位置的坐标,然后系统地与每个索引比较位置,直到得到一个位置,然后处理就这样。

由于本例中的 X 值小于所有其他值,因此将其放在数组列表的前面。 arraylist 位置确定每个图块的绘制位置。当你在这里松开鼠标时,选中的瓦片被保存在一个局部变量中,然后所有的瓦片都向右移动一个槽以适应新的变化,最后,选中的瓦片位置根据数组索引设置为(150,100) 0.