在Java中使用拖放功能进行纸牌游戏的操作。

huangapple go评论99阅读模式
英文:

Using Drag and Drop in Solitaire Game for Java

问题

  1. 我正在使用Java创建一个纸牌游戏我已经编写了纸牌牌组和大多数GUI的代码但是当我尝试将拖放功能添加到GUI中时我可以将纸牌拖动到不同的表格堆栈但是当我放下它时它只是粘贴在先前存在的纸牌上而不是将其堆叠在上面而且该纸牌没有从其旧位置移除你将如何解决这个问题
  2. 我已经尝试使用`exportAsDrag(jc,e,TransferHandler.MOVE);`并添加了代码来使其运行但似乎也不起作用
  3. 以下是三个类Solitaire类是GUI):
  4. ```java
  5. //导入语句
  6. import javax.swing.*;
  7. import java.awt.*;
  8. import java.awt.event.*;
  9. public class Solitaire extends JFrame {
  10. //实例变量
  11. private static final int CARD_WIDTH = 73;
  12. private static final int CARD_HEIGHT = (int)(CARD_WIDTH*1.49137931+.5);
  13. private static final int TOP_STACKS_X_DIFF = 435;
  14. private static final int TOP_STACKS_Y_DIFF = 30;
  15. private static final int WASTE_STACK_X_DIFF = 139;
  16. private static final int WASTE_STACK_Y_DIFF = 30;
  17. private static final int MAIN_STACKS_X_DIFF = 30;
  18. private static final int MAIN_STACKS_Y_DIFF = 40;
  19. private final JLabel newStack;
  20. private final JLabel wasteStack;
  21. private final JLabel[] topStacks;
  22. private final JLayeredPane[] mainStacks;
  23. private Card wasteCard;
  24. private Deck deckOfCards;
  25. //方法
  26. /**
  27. * 创建一个新的游戏屏幕GUI
  28. */
  29. public Solitaire() {
  30. //设置JFrame
  31. setTitle("Solitaire");
  32. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  33. setResizable(false);
  34. getContentPane().setBackground(new Color(0,153,0));
  35. //创建topStacks
  36. topStacks = new JLabel[4]; //初始化topStacks
  37. for (int index = 0; index < topStacks.length; index++) { //循环创建每个花色的堆栈
  38. topStacks[index] = new JLabel(); //创建新堆栈
  39. topStacks[index].setBounds((index*CARD_WIDTH) + (index*10) + TOP_STACKS_X_DIFF, TOP_STACKS_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //为每个顶部堆栈创建边界
  40. topStacks[index].setBorder(BorderFactory.createLineBorder(Color.BLACK)); //为每个顶部堆栈设置边框
  41. add(topStacks[index]); //添加到GUI
  42. } //结束for循环
  43. //创建wasteStack
  44. wasteStack = new JLabel(); //初始化wasteStack
  45. wasteStack.setBounds(WASTE_STACK_X_DIFF, WASTE_STACK_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //为waste堆栈创建边界
  46. wasteStack.setBorder(BorderFactory.createLineBorder(Color.BLACK)); //设置waste堆栈边界的边框
  47. add(wasteStack); //添加到GUI
  48. //创建newStack
  49. newStack = new JLabel(); //初始化newStack
  50. newStack.setBounds(WASTE_STACK_X_DIFF - CARD_WIDTH - 36, WASTE_STACK_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //为新堆栈创建边界
  51. newStack.setBorder(BorderFactory.createLineBorder(Color.BLACK)); //设置新堆栈边界的边框
  52. newStack.addMouseListener(new newStackOnClick()); //添加事件
  53. add(newStack); //添加到GUI
  54. //创建mainStacks
  55. mainStacks = new JLayeredPane[7]; //初始化mainStacks
  56. for (int index = 0; index < mainStacks.length; index++) { //循环创建7个堆栈
  57. mainStacks[index] = new JLayeredPane(); //创建新堆栈
  58. mainStacks[index].setBounds((index*CARD_WIDTH) + (index*36) + MAIN_STACKS_X_DIFF, MAIN_STACKS_Y_DIFF + (CARD_HEIGHT + 10), CARD_WIDTH, CARD_HEIGHT); //为每个主堆栈创建边界
  59. mainStacks[index].setBorder(BorderFactory.createLineBorder(Color.BLACK)); //为每个主堆栈设置边框
  60. add(mainStacks[index]); //添加到GUI
  61. } //结束for循环
  62. setLayout(null); //将布局更改为null
  63. setSize(800, 600); //定义窗口大小
  64. setVisible(true); //显示窗口
  65. startGame(); //开始游戏
  66. } //结束构造方法
  67. /**
  68. * 创建游戏。
  69. */
  70. private void startGame() {
  71. //创建并洗牌一副新牌
  72. deckOfCards = new Deck();
  73. deckOfCards.shuffleDeck();
  74. MouseListener ml = new MouseListener() {
  75. @Override
  76. public void mouseClicked(MouseEvent e) {}
  77. @Override
  78. public void mousePressed(MouseEvent e) {
  79. JComponent jc = (JComponent)e.getSource();
  80. TransferHandler th = jc.getTransferHandler();
  81. th.exportAsDrag(jc, e, TransferHandler.COPY);
  82. }
  83. @Override
  84. public void mouseReleased(MouseEvent e) {}
  85. @Override
  86. public void mouseEntered(MouseEvent e) {}
  87. @Override
  88. public void mouseExited(MouseEvent e) {}
  89. };
  90. for (int stack = 0; stack < mainStacks.length; stack++) { //循环遍历mainStacks中的堆栈
  91. int stackHeight = 0; //存储堆栈高度
  92. for (int cardInStack = 0; cardInStack <= stack; cardInStack++) { //循环添加每个堆栈中的纸牌
  93. Card placementCard = deckOfCards.drawCard(); //抽取纸牌
  94. placementCard.setIsFaceUp(false);
  95. //检查卡片是否是堆栈中的最后一张卡片
  96. if (stack == cardInStack) {
  97. placementCard.setIsFaceUp(true); //卡片正面朝上
  98. //调整图像大小并将其设置为placementCard
  99. ImageIcon placementCardFace = new ImageIcon(placementCard.getImagePath());
  100. Image placementCardScaled = placementCardFace.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  101. JLabel cardLabel = new JLabel(new ImageIcon(placementCardScaled));
  102. cardLabel.setBounds(0,card
  103. <details>
  104. <summary>英文:</summary>
  105. so I&#39;m creating a Solitaire game in Java. I have the card, deck, and most of the GUI coded out. However, when I go to implement drag and drop into the GUI, I am able to drag the cards to a different tableau stack, but when I drop it, it just pastes the card on the card that was previously there instead of stacking it on it. Plus, the card is not removed from its old location. How would you resolve this?
  106. I have tried using exportAsDrag(jc,e,TransferHandler.MOVE); and added code to make it run, but that didn&#39;t seem to work either.
  107. here are the three classes (Solitaire class is the GUI one):

//imports
import javax.swing.;
import java.awt.
;
import java.awt.event.*;

public class Solitaire extends JFrame {

  1. //instance variables
  2. private static final int CARD_WIDTH = 73;
  3. private static final int CARD_HEIGHT = (int)(CARD_WIDTH*1.49137931+.5);
  4. private static final int TOP_STACKS_X_DIFF = 435;
  5. private static final int TOP_STACKS_Y_DIFF = 30;
  6. private static final int WASTE_STACK_X_DIFF = 139;
  7. private static final int WASTE_STACK_Y_DIFF = 30;
  8. private static final int MAIN_STACKS_X_DIFF = 30;
  9. private static final int MAIN_STACKS_Y_DIFF = 40;
  10. private final JLabel newStack;
  11. private final JLabel wasteStack;
  12. private final JLabel[] topStacks;
  13. private final JLayeredPane[] mainStacks;
  14. private Card wasteCard;
  15. private Deck deckOfCards;
  16. //methods
  17. /**
  18. * Creates new form gameScreenGUI
  19. */
  20. public Solitaire() {
  21. //setting up JFrame
  22. setTitle(&quot;Solitaire&quot;);
  23. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  24. setResizable(false);
  25. getContentPane().setBackground(new Color(0,153,0));
  26. //Create the topStacks
  27. topStacks = new JLabel[4]; //initializing topStacks
  28. for (int index = 0; index &lt; topStacks.length; index++) { //loop through to create stack for each suit
  29. topStacks[index] = new JLabel(); //creating new stack
  30. topStacks[index].setBounds((index*CARD_WIDTH) + (index*10) + TOP_STACKS_X_DIFF, TOP_STACKS_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //creating the boundary for each top stack
  31. topStacks[index].setBorder(BorderFactory.createLineBorder(Color.BLACK)); //setting the border for each top stack
  32. add(topStacks[index]); //adding to GUI
  33. } //end of for loop
  34. //Create the wasteStack
  35. wasteStack = new JLabel(); //initializing wasteStack
  36. wasteStack.setBounds(WASTE_STACK_X_DIFF, WASTE_STACK_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //creating the boundary for the waste stack
  37. wasteStack.setBorder(BorderFactory.createLineBorder(Color.BLACK)); //setting the border for the boundary of the waste stack
  38. add(wasteStack); //adding to GUI
  39. //Create the newStack
  40. newStack = new JLabel(); //initializing newStack
  41. newStack.setBounds(WASTE_STACK_X_DIFF - CARD_WIDTH - 36, WASTE_STACK_Y_DIFF, CARD_WIDTH, CARD_HEIGHT); //creating the boundary for the new stack
  42. newStack.setBorder(BorderFactory.createLineBorder(Color.BLACK)); //setting the border for the boundary of the new stack
  43. newStack.addMouseListener(new newStackOnClick()); //adding event
  44. add(newStack); //adding to GUI
  45. //Create the mainStacks
  46. mainStacks = new JLayeredPane[7]; //initializing mainStacks
  47. for (int index = 0; index &lt; mainStacks.length; index++) { //loop through to create 7 stacks
  48. mainStacks[index] = new JLayeredPane(); //creating new stack
  49. mainStacks[index].setBounds((index*CARD_WIDTH) + (index*36) + MAIN_STACKS_X_DIFF, MAIN_STACKS_Y_DIFF + (CARD_HEIGHT + 10), CARD_WIDTH, CARD_HEIGHT); //creating the boundary for each main stack
  50. mainStacks[index].setBorder(BorderFactory.createLineBorder(Color.BLACK)); //setting the border for each main stack
  51. add(mainStacks[index]); //add to GUI
  52. } //end of for loop
  53. setLayout(null); //changing to null layout
  54. setSize(800, 600); //defining size of window
  55. setVisible(true); //displaying window
  56. startGame(); //starts the game
  57. } //end of constructor method
  58. /**
  59. * This method creates the game.
  60. */
  61. private void startGame() {
  62. //creates and shuffles a new deck
  63. deckOfCards = new Deck();
  64. deckOfCards.shuffleDeck();
  65. MouseListener ml = new MouseListener() {
  66. @Override
  67. public void mouseClicked(MouseEvent e) {}
  68. @Override
  69. public void mousePressed(MouseEvent e) {
  70. JComponent jc = (JComponent)e.getSource();
  71. TransferHandler th = jc.getTransferHandler();
  72. th.exportAsDrag(jc, e, TransferHandler.COPY);
  73. }
  74. @Override
  75. public void mouseReleased(MouseEvent e) {}
  76. @Override
  77. public void mouseEntered(MouseEvent e) {}
  78. @Override
  79. public void mouseExited(MouseEvent e) {}
  80. };
  81. for (int stack = 0; stack &lt; mainStacks.length; stack++) { //loop through the stacks in the mainStacks
  82. int stackHeight = 0; //stores the height of the stack
  83. for (int cardInStack = 0; cardInStack &lt;= stack; cardInStack++) { //loop through to add the cards in each Stack
  84. Card placementCard = deckOfCards.drawCard(); //draws card
  85. placementCard.setIsFaceUp(false);
  86. //checking if the card is the last card in the stack
  87. if (stack == cardInStack) {
  88. placementCard.setIsFaceUp(true); //card is facing up
  89. //sizes the image and sets it to placementCard
  90. ImageIcon placementCardFace = new ImageIcon(placementCard.getImagePath());
  91. Image placementCardScaled = placementCardFace.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  92. JLabel cardLabel = new JLabel(new ImageIcon(placementCardScaled));
  93. cardLabel.setBounds(0,cardInStack*22, CARD_WIDTH, CARD_HEIGHT);
  94. cardLabel.addMouseListener(ml);
  95. cardLabel.setTransferHandler(new TransferHandler(&quot;icon&quot;));
  96. mainStacks[stack].add(cardLabel, Integer.valueOf(cardInStack));
  97. } //end of if statement
  98. //if statement to check whether the card should be revealed or not
  99. if (!placementCard.getIsFaceUp()) { //hide cardFront
  100. //sizes the image and sets it to placementCard
  101. ImageIcon placementCardBack = new ImageIcon(Card.getBackImagePath());
  102. Image placementCardScaled = placementCardBack.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  103. JLabel cardLabel = new JLabel(new ImageIcon(placementCardScaled));
  104. cardLabel.setBounds(0,cardInStack*22, CARD_WIDTH, CARD_HEIGHT);
  105. mainStacks[stack].add(cardLabel, Integer.valueOf(cardInStack));
  106. } //end of if statement
  107. stackHeight = CARD_HEIGHT + (22*stack); //increments the stack height with each new card
  108. } //end of for loop
  109. mainStacks[stack].setSize(CARD_WIDTH, stackHeight); //sets the size of the stack so that all cards show
  110. } //end of for loop
  111. //sizes the image and sets it to newCard
  112. ImageIcon cardBack = new ImageIcon(Card.getBackImagePath());
  113. Image cardBackScaled = cardBack.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  114. newStack.setIcon(new ImageIcon(cardBackScaled));
  115. wasteCard = deckOfCards.drawCard(); //new card from pile to possibly add to mainStacks
  116. wasteCard.setIsFaceUp(true); //sets card facing up
  117. //sizes the image and sets it to wasteCard
  118. ImageIcon wasteCardFace = new ImageIcon(wasteCard.getImagePath());
  119. Image wasteCardFaceScaled = wasteCardFace.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  120. wasteStack.addMouseListener(ml);
  121. wasteStack.setTransferHandler(new TransferHandler(&quot;icon&quot;));
  122. wasteStack.setIcon(new ImageIcon(wasteCardFaceScaled));
  123. } //end of startGame method
  124. private void newStackClick() {
  125. if(!deckOfCards.isEmpty()) {
  126. wasteCard = deckOfCards.drawCard();
  127. System.out.println(wasteCard);
  128. wasteCard.setIsFaceUp(true);
  129. ImageIcon wasteCardFace = new ImageIcon(wasteCard.getImagePath());
  130. Image wasteCardScaled = wasteCardFace.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  131. wasteStack.setIcon(new ImageIcon(wasteCardScaled));
  132. } else {
  133. resetNewStack();
  134. } //end of if statement
  135. } //end of newStackClick method
  136. private void resetNewStack() {
  137. deckOfCards.resetDrawCardIndex();
  138. deckOfCards.shuffleDeck();
  139. wasteCard = deckOfCards.drawCard();
  140. wasteCard.setIsFaceUp(true);
  141. ImageIcon wasteCardFace = new ImageIcon(wasteCard.getImagePath());
  142. Image wasteCardScaled = wasteCardFace.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  143. wasteStack.setIcon(new ImageIcon(wasteCardScaled));
  144. ImageIcon cardBack = new ImageIcon(Card.getBackImagePath());
  145. Image cardBackScaled = cardBack.getImage().getScaledInstance(CARD_WIDTH, CARD_HEIGHT, Image.SCALE_SMOOTH);
  146. newStack.setIcon(new ImageIcon(cardBackScaled));
  147. } //end of resetNewStack method
  148. private class newStackOnClick extends MouseAdapter {
  149. @Override
  150. public void mouseClicked(MouseEvent e) {
  151. newStackClick();
  152. } //end of mouseClicked method
  153. } //end of newStackOnClick class
  154. public static void main(String[] args) {
  155. new Solitaire();
  156. } //end of main method

} //end of SolitaireJLP class

public class Card {
//instance variables
private final Suit SUIT;
private final Rank RANK;
private boolean isFaceUp;

  1. //methods
  2. /**
  3. * This is the constructor method for the Card class.
  4. * @param suit - the suit to be assigned to the card.
  5. * @param rank - the rank to be assigned to the card.
  6. */
  7. public Card(Suit suit, Rank rank) {
  8. this.SUIT = suit;
  9. this.RANK = rank;
  10. this.isFaceUp = false;
  11. } //end of constructor
  12. /**
  13. * This method gives the user the suit of the Card.
  14. * @return Suit - the suit of the Card.
  15. */
  16. public Suit getSuit() {
  17. return this.SUIT;
  18. } //end of getSuit method
  19. /**
  20. * This method gives the user the rank of the Card.
  21. * @return Rank - the rank of the Card.
  22. */
  23. public Rank getRank() {
  24. return this.RANK;
  25. } //end of getRank method
  26. /**
  27. * This method gives whether the Card is faced up or not.
  28. * @return Boolean - true or false based on if the Card is facing up.
  29. */
  30. public boolean getIsFaceUp() {
  31. return this.isFaceUp;
  32. } //end of getIsFaceUp method
  33. /**
  34. * This method sets the isFaceUp variable to true if the card is facing up in the game.
  35. */
  36. public void setIsFaceUp(boolean b) {
  37. this.isFaceUp = b;
  38. } //end of setIsFaceUp method
  39. /**
  40. * This method determines if the Card is from a red suit.
  41. * @return Boolean - true or false if card is red
  42. */
  43. public boolean isRed() {
  44. return this.SUIT == Suit.HEARTS || this.SUIT == Suit.DIAMONDS;
  45. } //end of isRed method
  46. /**
  47. * This method determines if the Card is from a black suit.
  48. * @return a Boolean true or false if card is black
  49. */
  50. public boolean isBlack() {
  51. return this.SUIT == Suit.CLUBS || this.SUIT == Suit.SPADES;
  52. } //end of isBlack method
  53. /**
  54. * This method determines if the card can be stacked on the card behind it.
  55. * @return a Boolean true or false if it can be stacked
  56. */
  57. public boolean stackable(Card card) {
  58. return this.isRed() != card.isRed();
  59. } //end of stackable method
  60. /**
  61. * This method gives the name of each card.
  62. * @return a string that has two letters- the first letter of the rank and the first letter of the suit.
  63. */
  64. public String getName() {
  65. String number = &quot;&quot;; //variable declaration
  66. switch(RANK) { //switch to assign rank name
  67. case ACE -&gt; number = &quot;A&quot;; //case
  68. case TWO -&gt; number = &quot;2&quot;; //case
  69. case THREE -&gt; number = &quot;3&quot;; //case
  70. case FOUR -&gt; number = &quot;4&quot;; //case
  71. case FIVE -&gt; number = &quot;5&quot;; //case
  72. case SIX -&gt; number = &quot;6&quot;; //case
  73. case SEVEN -&gt; number = &quot;7&quot;; //case
  74. case EIGHT -&gt; number = &quot;8&quot;; //case
  75. case NINE -&gt; number = &quot;9&quot;; //case
  76. case TEN -&gt; number = &quot;10&quot;; //case
  77. case JACK -&gt; number = &quot;J&quot;; //case
  78. case QUEEN -&gt; number = &quot;Q&quot;; //case
  79. case KING -&gt; number = &quot;K&quot;; //case
  80. } //end of switch
  81. String suitName = &quot;&quot;; //variable declaration
  82. switch(SUIT) { //switch to assign suit name
  83. case HEARTS -&gt; suitName = &quot;H&quot;; //case
  84. case DIAMONDS -&gt; suitName = &quot;D&quot;; //case
  85. case SPADES -&gt; suitName = &quot;S&quot;; //case
  86. case CLUBS -&gt; suitName = &quot;C&quot;; //case
  87. } //end of switch
  88. return number + suitName; //return statement
  89. } //end of getName method
  90. /**
  91. * This method gives the path to a corresponding image.
  92. * @return String - returns the path of the image corresponding with the card.
  93. */
  94. public String getImagePath() {
  95. return &quot;C:\\ICS3U_SUMMATIVE_SOLITAIRE\\src\\cards\\&quot; + getName().substring(1,getName().length()) + &quot;\\&quot; + getName() + &quot;.jpg&quot;; //return statement
  96. } //end of getImage method
  97. /**
  98. * This method gives the file path to the back of the card image.
  99. * @return String the file path to the card back image
  100. */
  101. public static String getBackImagePath() {
  102. return &quot;C:\\ICS3U_SUMMATIVE_SOLITAIRE\\src\\CardBack.jpg&quot;;
  103. } //end of getImageBackPath method
  104. @Override
  105. /**
  106. * This method returns the description about the instance variables.
  107. * @return String - rank and suit of card along with image path.
  108. */
  109. public String toString() {
  110. return this.RANK + &quot; of &quot; + this.SUIT + &quot; ---- &quot; + getImagePath();
  111. }

} //end of Card class

//imports
import java.util.ArrayList;
import java.util.Collections;

public class Deck {

  1. //instance variables
  2. private final ArrayList&lt;Card&gt; cards;
  3. private int drawCardIndex;
  4. //methods
  5. /**
  6. * This constructor for the Deck class creates all 52 cards and adds them to cards List.
  7. */
  8. public Deck() {
  9. cards = new ArrayList&lt;&gt;(); //creating new deck
  10. for (Suit suit: Suit.values()) { //loops through suits
  11. for (Rank rank: Rank.values()) { //loops through ranks
  12. cards.add(new Card(suit, rank)); //adds a unique Card to cards
  13. }
  14. }
  15. drawCardIndex = 0; //initializes index
  16. } //end of constructor
  17. /**
  18. * This method returns the size of the deck.
  19. * @return int - size of deck
  20. */
  21. public int getSize() {
  22. return cards.size();
  23. } //end of getSize method
  24. /**
  25. * This method returns a drawn card in the deck of cards.
  26. * @return Card - a new drawn card in the deck of cards.
  27. */
  28. public Card drawCard() {
  29. if (drawCardIndex&lt;cards.size()) { //checks if all of the cards have been drawn
  30. Card card = cards.get(drawCardIndex); //draws a card
  31. drawCardIndex++; //increments
  32. return card; //return statement
  33. }
  34. return null; //returns null if all of the cards have already been drawn
  35. } //end of drawCard method
  36. /**
  37. * This method shuffles the deck of cards.
  38. */
  39. public void shuffleDeck() {
  40. Collections.shuffle(cards); //mixes ArrayList
  41. resetDrawCardIndex(); //resets the drawCardIndex variable
  42. } //end of shuffleDeck method
  43. /**
  44. * This method resets the drawCardIndex.
  45. */
  46. public void resetDrawCardIndex() {
  47. drawCardIndex = 0;
  48. } //end of resetDrawCardIndex method
  49. /**
  50. * This method checks if all of the cards have been drawn.
  51. * @return Boolean true or false based on if all the cards have been drawn or not.
  52. */
  53. public boolean isEmpty() {
  54. return cards.size() &lt;= drawCardIndex;
  55. } //end of isEmpty method

} //end of Deck class

  1. </details>
  2. # 答案1
  3. **得分**: 1
  4. 以下是您提供的代码的翻译部分:
  5. ```java
  6. 使用我上面评论中提到的概念,我想出了一个简单的示例:
  7. import java.awt.*;
  8. import java.awt.datatransfer.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import javax.swing.*;
  12. import javax.swing.border.*;
  13. import javax.swing.plaf.*;
  14. import javax.swing.text.*;
  15. import javax.swing.border.*;
  16. import java.io.*;
  17. public class DragCards extends JPanel
  18. {
  19. private static DataFlavor COMPONENT_FLAVOR;
  20. private PanelHandler panelHandler = new PanelHandler();
  21. private ComponentHandler componentHandler = new ComponentHandler();
  22. private MouseListener dragListener;
  23. private Dimension cardSize = new Dimension(100, 175);
  24. public DragCards()
  25. {
  26. try
  27. {
  28. COMPONENT_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";;class=\"" + Component[].class.getName() + "\"");
  29. }
  30. catch(Exception e) { System.out.println(e); }
  31. dragListener = new MouseAdapter()
  32. {
  33. @Override
  34. public void mousePressed(MouseEvent e)
  35. {
  36. JComponent c = (JComponent) e.getSource();
  37. TransferHandler handler = c.getTransferHandler();
  38. handler.exportAsDrag(c, e, TransferHandler.MOVE);
  39. }
  40. };
  41. setLayout( new BorderLayout() );
  42. add(createDeckPanel(), BorderLayout.PAGE_START);
  43. add(createStacksPanel(), BorderLayout.CENTER);
  44. }
  45. private JPanel createDeckPanel()
  46. {
  47. JPanel deckPanel = new JPanel( new OverlapLayout( new Point(0, 0) ) );
  48. for (int i = 0; i < 10; i++)
  49. {
  50. JLabel label = new JLabel( "Card: " + i );
  51. label.setVerticalAlignment(JLabel.TOP);
  52. label.setBorder( new LineBorder(Color.BLACK) );
  53. label.setOpaque( true );
  54. label.setBackground( Color.WHITE );
  55. label.setPreferredSize( cardSize );
  56. label.addMouseListener( dragListener );
  57. label.setTransferHandler( componentHandler );
  58. deckPanel.add( label );
  59. }
  60. JPanel wrapper = new JPanel();
  61. wrapper.add( deckPanel );
  62. return wrapper;
  63. }
  64. private JPanel createStacksPanel()
  65. {
  66. JPanel stackPanels = new JPanel( new GridLayout(0, 4, 10, 10) );
  67. Dimension stackDimension = new Dimension(cardSize.width, cardSize.height + 200);
  68. for (int i = 0; i < 4; i++)
  69. {
  70. JPanel stackPanel = new JPanel( new OverlapLayout( new Point(0, 20) ) );
  71. stackPanel.setBackground( Color.YELLOW );
  72. stackPanel.setBorder( new EmptyBorder(10, 0, 0, 0) );
  73. stackPanel.setPreferredSize( stackDimension );
  74. stackPanel.setTransferHandler( panelHandler );
  75. stackPanels.add( stackPanel );
  76. }
  77. JPanel wrapper = new JPanel();
  78. wrapper.add( stackPanels );
  79. return (wrapper );
  80. }
  81. class ComponentHandler extends TransferHandler
  82. {
  83. @Override
  84. public int getSourceActions(JComponent c)
  85. {
  86. // setDragImage( ScreenImage.createImage(c) );
  87. return MOVE;
  88. }
  89. @Override
  90. public Transferable createTransferable(final JComponent c)
  91. {
  92. return new Transferable()
  93. {
  94. @Override
  95. public Object getTransferData(DataFlavor flavor)
  96. {
  97. Component[] components = new Component[1];
  98. components[0] = c;
  99. return components;
  100. }
  101. @Override
  102. public DataFlavor[] getTransferDataFlavors()
  103. {
  104. DataFlavor[] flavors = new DataFlavor[1];
  105. flavors[0] = DragCards.COMPONENT_FLAVOR;
  106. return flavors;
  107. }
  108. @Override
  109. public boolean isDataFlavorSupported(DataFlavor flavor)
  110. {
  111. return flavor.equals(DragCards.COMPONENT_FLAVOR);
  112. }
  113. };
  114. }
  115. @Override
  116. public void exportDone(JComponent c, Transferable t, int action)
  117. {
  118. }
  119. }
  120. class PanelHandler extends TransferHandler
  121. {
  122. @Override
  123. public boolean canImport(TransferSupport support)
  124. {
  125. if (!support.isDrop())
  126. {
  127. return false;
  128. }
  129. boolean canImport = support.isDataFlavorSupported(DragCards.COMPONENT_FLAVOR);
  130. return canImport;
  131. }
  132. @Override
  133. public boolean importData(TransferSupport support)
  134. {
  135. if (!canImport(support))
  136. {
  137. return false;
  138. }
  139. Component[] components;
  140. try
  141. {
  142. components = (Component[])support.getTransferable().getTransferData(DragCards.COMPONENT_FLAVOR);
  143. }
  144. catch (Exception e)
  145. {
  146. e.printStackTrace();
  147. return false;
  148. }
  149. Component component = components[0];
  150. Container parent = component.getParent();
  151. Container container = (Container)support.getComponent();
  152. container.add(component);
  153. container.getParent().revalidate();
  154. container.getParent().repaint();
  155. parent.revalidate();
  156. parent.repaint();
  157. return true;
  158. }
  159. }
  160. private static void createAndShowUI()
  161. {
  162. JFrame frame = new JFrame("DragCards");
  163. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  164. frame.add( new DragCards());
  165. frame.pack();
  166. frame.setLocationByPlatform( true );
  167. frame.setVisible( true );
  168. }
  169. public static void main(String[] args)
  170. {
  171. EventQueue.invokeLater(new Runnable()
  172. {
  173. public void run()
  174. {
  175. createAndShowUI();
  176. }
  177. });
  178. }
  179. }

希望这对您有所帮助!如果您需要任何进一步的协助,请随时告诉我。

英文:

Using concepts from my comments above I came up with a simple example:

  1. import java.awt.*;
  2. import java.awt.datatransfer.*;
  3. import java.awt.event.*;
  4. import java.beans.*;
  5. import javax.swing.*;
  6. import javax.swing.border.*;
  7. import javax.swing.plaf.*;
  8. import javax.swing.text.*;
  9. import javax.swing.border.*;
  10. import java.io.*;
  11. public class DragCards extends JPanel
  12. {
  13. private static DataFlavor COMPONENT_FLAVOR;
  14. private PanelHandler panelHandler = new PanelHandler();
  15. private ComponentHandler componentHandler = new ComponentHandler();
  16. private MouseListener dragListener;
  17. private Dimension cardSize = new Dimension(100, 175);
  18. public DragCards()
  19. {
  20. try
  21. {
  22. COMPONENT_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + &quot;;class=\&quot;&quot; + Component[].class.getName() + &quot;\&quot;&quot;);
  23. }
  24. catch(Exception e) { System.out.println(e); }
  25. dragListener = new MouseAdapter()
  26. {
  27. @Override
  28. public void mousePressed(MouseEvent e)
  29. {
  30. JComponent c = (JComponent) e.getSource();
  31. TransferHandler handler = c.getTransferHandler();
  32. handler.exportAsDrag(c, e, TransferHandler.MOVE);
  33. }
  34. };
  35. setLayout( new BorderLayout() );
  36. add(createDeckPanel(), BorderLayout.PAGE_START);
  37. add(createStacksPanel(), BorderLayout.CENTER);
  38. }
  39. private JPanel createDeckPanel()
  40. {
  41. JPanel deckPanel = new JPanel( new OverlapLayout( new Point(0, 0) ) );
  42. for (int i = 0; i &lt; 10; i++)
  43. {
  44. JLabel label = new JLabel( &quot;Card: &quot; + i );
  45. label.setVerticalAlignment(JLabel.TOP);
  46. label.setBorder( new LineBorder(Color.BLACK) );
  47. label.setOpaque( true );
  48. label.setBackground( Color.WHITE );
  49. label.setPreferredSize( cardSize );
  50. label.addMouseListener( dragListener );
  51. label.setTransferHandler( componentHandler );
  52. deckPanel.add( label );
  53. }
  54. JPanel wrapper = new JPanel();
  55. wrapper.add( deckPanel );
  56. return wrapper;
  57. }
  58. private JPanel createStacksPanel()
  59. {
  60. JPanel stackPanels = new JPanel( new GridLayout(0, 4, 10, 10) );
  61. Dimension stackDimension = new Dimension(cardSize.width, cardSize.height + 200);
  62. for (int i = 0; i &lt; 4; i++)
  63. {
  64. JPanel stackPanel = new JPanel( new OverlapLayout( new Point(0, 20) ) );
  65. stackPanel.setBackground( Color.YELLOW );
  66. stackPanel.setBorder( new EmptyBorder(10, 0, 0, 0) );
  67. stackPanel.setPreferredSize( stackDimension );
  68. stackPanel.setTransferHandler( panelHandler );
  69. stackPanels.add( stackPanel );
  70. }
  71. JPanel wrapper = new JPanel();
  72. wrapper.add( stackPanels );
  73. return (wrapper );
  74. }
  75. class ComponentHandler extends TransferHandler
  76. {
  77. @Override
  78. public int getSourceActions(JComponent c)
  79. {
  80. // setDragImage( ScreenImage.createImage(c) );
  81. return MOVE;
  82. }
  83. @Override
  84. public Transferable createTransferable(final JComponent c)
  85. {
  86. return new Transferable()
  87. {
  88. @Override
  89. public Object getTransferData(DataFlavor flavor)
  90. {
  91. Component[] components = new Component[1];
  92. components[0] = c;
  93. return components;
  94. }
  95. @Override
  96. public DataFlavor[] getTransferDataFlavors()
  97. {
  98. DataFlavor[] flavors = new DataFlavor[1];
  99. flavors[0] = DragCards.COMPONENT_FLAVOR;
  100. return flavors;
  101. }
  102. @Override
  103. public boolean isDataFlavorSupported(DataFlavor flavor)
  104. {
  105. return flavor.equals(DragCards.COMPONENT_FLAVOR);
  106. }
  107. };
  108. }
  109. @Override
  110. public void exportDone(JComponent c, Transferable t, int action)
  111. {
  112. }
  113. }
  114. class PanelHandler extends TransferHandler
  115. {
  116. @Override
  117. public boolean canImport(TransferSupport support)
  118. {
  119. if (!support.isDrop())
  120. {
  121. return false;
  122. }
  123. boolean canImport = support.isDataFlavorSupported(DragCards.COMPONENT_FLAVOR);
  124. return canImport;
  125. }
  126. @Override
  127. public boolean importData(TransferSupport support)
  128. {
  129. if (!canImport(support))
  130. {
  131. return false;
  132. }
  133. Component[] components;
  134. try
  135. {
  136. components = (Component[])support.getTransferable().getTransferData(DragCards.COMPONENT_FLAVOR);
  137. }
  138. catch (Exception e)
  139. {
  140. e.printStackTrace();
  141. return false;
  142. }
  143. Component component = components[0];
  144. Container parent = component.getParent();
  145. Container container = (Container)support.getComponent();
  146. container.add(component);
  147. container.getParent().revalidate();
  148. container.getParent().repaint();
  149. parent.revalidate();
  150. parent.repaint();
  151. return true;
  152. }
  153. }
  154. private static void createAndShowUI()
  155. {
  156. JFrame frame = new JFrame(&quot;DragCards&quot;);
  157. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  158. frame.add( new DragCards());
  159. frame.pack();
  160. frame.setLocationByPlatform( true );
  161. frame.setVisible( true );
  162. }
  163. public static void main(String[] args)
  164. {
  165. EventQueue.invokeLater(new Runnable()
  166. {
  167. public void run()
  168. {
  169. createAndShowUI();
  170. }
  171. });
  172. }
  173. }

Notes:

  1. If you want to set the setDragImage(...) method you will need to get the Screen Image code.

  2. When dragging to on of the 4 stack panels, the mouse must be on the panel, not the label. If you want the logic to work when the mouse is over a label, then (I think - but have not tried) you would need to add the import logic into the ComponentHandler class. This logic should be similar to the import logic in the panel class.

Or the second approach using custom dragging code might look something like:

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import javax.swing.*;
  4. import javax.swing.border.*;
  5. public class DragCards2 extends JPanel implements MouseListener, MouseMotionListener
  6. {
  7. private Dimension cardSize = new Dimension(100, 175);
  8. private JPanel deckPanel;
  9. private JPanel stacksPanel;
  10. private Component card;
  11. int xAdjustment;
  12. int yAdjustment;
  13. private MouseListener dragListener;
  14. public DragCards2()
  15. {
  16. setLayout( new BorderLayout() );
  17. add(createDeckPanel(), BorderLayout.PAGE_START);
  18. add(createStacksPanel(), BorderLayout.CENTER);
  19. }
  20. private JPanel createDeckPanel()
  21. {
  22. deckPanel = new JPanel( new OverlapLayout( new Point(0, 0) ) );
  23. for (int i = 0; i &lt; 10; i++)
  24. {
  25. JLabel label = new JLabel( &quot;Card: &quot; + i );
  26. label.setVerticalAlignment(JLabel.TOP);
  27. label.setBorder( new LineBorder(Color.BLACK) );
  28. label.setOpaque( true );
  29. label.setBackground( Color.WHITE );
  30. label.setPreferredSize( cardSize );
  31. deckPanel.add( label );
  32. }
  33. deckPanel.addMouseListener( this );
  34. deckPanel.addMouseMotionListener( this );
  35. JPanel wrapper = new JPanel();
  36. wrapper.add( deckPanel );
  37. return wrapper;
  38. }
  39. private JPanel createStacksPanel()
  40. {
  41. stacksPanel = new JPanel( new GridLayout(0, 4, 10, 10) );
  42. Dimension stackDimension = new Dimension(cardSize.width, cardSize.height + 200);
  43. for (int i = 0; i &lt; 4; i++)
  44. {
  45. JPanel stackPanel = new JPanel( new OverlapLayout( new Point(0, 20) ) );
  46. stackPanel.setBackground( Color.YELLOW );
  47. stackPanel.setBorder( new EmptyBorder(10, 0, 0, 0) );
  48. stackPanel.setPreferredSize( stackDimension );
  49. stacksPanel.add( stackPanel );
  50. }
  51. JPanel wrapper = new JPanel();
  52. wrapper.add( stacksPanel );
  53. return (wrapper );
  54. }
  55. /*
  56. ** Add the card to the dragging layer so it can be moved
  57. */
  58. public void mousePressed(MouseEvent e)
  59. {
  60. JPanel deckPanel = (JPanel)e.getComponent();
  61. card = deckPanel.getComponent( 0 );
  62. if (card instanceof JPanel) return;
  63. Point parentLocation = card.getParent().getLocation();
  64. xAdjustment = parentLocation.x - e.getX();
  65. yAdjustment = parentLocation.y - e.getY();
  66. card.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
  67. JLayeredPane lp = getRootPane().getLayeredPane();
  68. lp.add(card, JLayeredPane.DRAG_LAYER);
  69. setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
  70. }
  71. /*
  72. ** Move the chess piece around
  73. */
  74. public void mouseDragged(MouseEvent me)
  75. {
  76. if (card == null) return;
  77. int x = me.getX() + xAdjustment;
  78. int y = me.getY() + yAdjustment;
  79. card.setLocation(x, y);
  80. }
  81. /*
  82. ** Drop the card back onto the game board
  83. */
  84. public void mouseReleased(MouseEvent e)
  85. {
  86. setCursor(null);
  87. if (card == null) return;
  88. // Make sure the card is no longer painted on the layered pane
  89. card.setVisible(false);
  90. // check to see if card was dragged to a stack
  91. JPanel stackPanel = null;
  92. Point localPoint = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), stacksPanel);
  93. for (int i = 0; i &lt; stacksPanel.getComponentCount(); i++)
  94. {
  95. JPanel panel = (JPanel)stacksPanel.getComponent(i);
  96. if (panel.getBounds().contains(localPoint))
  97. {
  98. stackPanel = panel;
  99. break;
  100. }
  101. }
  102. if (stackPanel == null)
  103. deckPanel.add( card );
  104. else
  105. stackPanel.add( card );
  106. card.setVisible(true);
  107. }
  108. public void mouseClicked(MouseEvent e) {}
  109. public void mouseMoved(MouseEvent e) {}
  110. public void mouseEntered(MouseEvent e) {}
  111. public void mouseExited(MouseEvent e) {}
  112. private static void createAndShowUI()
  113. {
  114. JFrame frame = new JFrame(&quot;DragCards2&quot;);
  115. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  116. frame.add( new DragCards2());
  117. frame.pack();
  118. frame.setLocationByPlatform( true );
  119. frame.setVisible( true );
  120. }
  121. public static void main(String[] args)
  122. {
  123. EventQueue.invokeLater(new Runnable()
  124. {
  125. public void run()
  126. {
  127. createAndShowUI();
  128. }
  129. });
  130. }
  131. }

Both examples use the Overlap Layout to allow for easy stacking of the cards.

huangapple
  • 本文由 发表于 2023年6月16日 14:25:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76487451.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定