gpt4 book ai didi

Java:如何将控件而不是其数据拖放到新位置?

转载 作者:行者123 更新时间:2023-12-02 00:27:39 26 4
gpt4 key购买 nike

在Java中,当被拖动的项目是源控件本身时,执行拖放的最佳方法是什么?我知道控件也只不过是数据,但差异确实会影响 UI。

我正在创建一个纸牌风格的游戏,其中有从 JLabel 派生的 Card 类的卡片对象。我想将该卡拖放到另一个位置,方法是将其放到尚未命名的“目标”控件上。在拖动过程中,我希望卡在视觉上随鼠标移动,当放下时,我希望它移动到此目标对象或返回到其先前的位置。

我已经完成了各种 D-n-D 测试,但没有发现任何可以在 Java 的 D-D 正确规则下工作的东西。

例如,如果我使用真正的 D-n-D 拖动卡片对象,我只能创建卡片的重影图像,而不能创建实体图像。另外,光标发生了变化,我宁愿它没有发生变化(我想我可以解决这个问题),并且源控件仍然可见(尽管在拖动过程中应该很容易使其透明)

另一方面,我可以通过监听 MouseMotionListener.mouseDragged() 事件并手动将卡移动到新位置来精美地拖动卡。这很好用,但它没有遵循正确的 D-n-D,因为这不会通知其他控件的拖动。我想我可以创建自己的系统来通知其他控件,但这不会使用 Java 真正的 D-n-D。另外,如果我将真正的 Java d-n-d 东西与这种在 mouseDragged 期间字面移动卡片的方法混合在一起,那么我认为真正的 D-n-D 东西将永远不会工作,因为从技术上讲,鼠标永远不会直接位于除被拖动的卡片之外的任何其他控件上。这个方向看起来像是一个粗暴的黑客。

我希望这是有道理的。我在跟踪样本时遇到了问题,因为它们看起来都非常不同,而且我花了很多时间研究的一个样本看起来比 D-n-D 在 1.4 版中进行重大修改之前几年。

最佳答案

在单个应用程序周围而不是在应用程序之间拖动组件的一种方法是使用 JLayeredPane。例如,请在此处查看我的代码:dragging a jlabel around the screen

扑克牌的示例可能如下所示(只要扑克牌图像保持有效!):

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.*;

public class PlayingCardTest {


public static void main(String[] args) {
String pathToDeck = "http://www.jfitz.com/cards/classic-playing-cards.png";
try {
final List<ImageIcon> cardImgList = CreateCards.createCardIconList(pathToDeck);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Moving Cards");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CardGameTable(cardImgList, frame));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}

@SuppressWarnings("serial")
class CardGameTable extends JLayeredPane {

private static final int PREF_W = 600;
private static final int PREF_H = 400;
private static final Color BASE_COLOR = new Color(0, 80, 0);
private static final int CARD_COUNT = 20;
private static final int WIDTH_SHOWING = 20;

private JPanel basePane = new JPanel(null);

public CardGameTable(List<ImageIcon> cardImgList, final JFrame frame) {
basePane.setSize(getPreferredSize());
basePane.setBackground(BASE_COLOR);
add(basePane, JLayeredPane.DEFAULT_LAYER);

final MyMouseAdapter myMouseAdapter = new MyMouseAdapter(this, basePane);
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);

for (int i = 0; i < CARD_COUNT; i++) {
JLabel card = new JLabel(cardImgList.remove(0));
card.setSize(card.getPreferredSize());
int x = (PREF_W / 2) + WIDTH_SHOWING * (CARD_COUNT - 2 * i) / 2 -
card.getPreferredSize().width / 2;
int y = PREF_H - card.getPreferredSize().height - WIDTH_SHOWING * 2;
card.setLocation(x, y);
basePane.add(card);
}
}

@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}

}

class MyMouseAdapter extends MouseAdapter {
private JLabel selectedCard = null;
private JLayeredPane cardGameTable = null;
private JPanel basePane = null;
private int deltaX = 0;
private int deltaY = 0;

public MyMouseAdapter(JLayeredPane gameTable, JPanel basePane) {
this.cardGameTable = gameTable;
this.basePane = basePane;
}

@Override
public void mousePressed(MouseEvent mEvt) {
Component comp = basePane.getComponentAt(mEvt.getPoint());
if (comp != null && comp instanceof JLabel) {
selectedCard = (JLabel) comp;
basePane.remove(selectedCard);
basePane.revalidate();
basePane.repaint();

cardGameTable.add(selectedCard, JLayeredPane.DRAG_LAYER);
cardGameTable.revalidate();
cardGameTable.repaint();
deltaX = mEvt.getX() - selectedCard.getX();
deltaY = mEvt.getY() - selectedCard.getY();
}
}

@Override
public void mouseReleased(MouseEvent mEvt) {
if (selectedCard != null) {
cardGameTable.remove(selectedCard);
cardGameTable.revalidate();
cardGameTable.repaint();

basePane.add(selectedCard, 0);
basePane.revalidate();
basePane.repaint();
selectedCard = null;
}
}

@Override
public void mouseDragged(MouseEvent mEvt) {
if (selectedCard != null) {
int x = mEvt.getX() - deltaX;
int y = mEvt.getY() - deltaY;
selectedCard.setLocation(x, y);
cardGameTable.revalidate();
cardGameTable.repaint();
}
}
}

class CreateCards {
private static final int SUIT_COUNT = 4;
private static final int RANK_COUNT = 13;

public static List<ImageIcon> createCardIconList(String pathToDeck)
throws MalformedURLException, IOException {
BufferedImage fullDeckImg = ImageIO.read(new URL(pathToDeck));
int width = fullDeckImg.getWidth();
int height = fullDeckImg.getHeight();
List<ImageIcon> iconList = new ArrayList<ImageIcon>();

for (int suit = 0; suit < SUIT_COUNT; suit++) {
for (int rank = 0; rank < RANK_COUNT; rank++) {
int x = (rank * width) / RANK_COUNT;
int y = (suit * height) / SUIT_COUNT;
int w = width / RANK_COUNT;
int h = height / SUIT_COUNT;
BufferedImage cardImg = fullDeckImg.getSubimage(x, y, w, h);
iconList.add(new ImageIcon(cardImg));
}
}
Collections.shuffle(iconList);
return iconList;
}
}

关于Java:如何将控件而不是其数据拖放到新位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9692465/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com