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

2024-01-09

在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。例如,请在此处查看我的代码:在屏幕上拖动 jlabel https://stackoverflow.com/a/4894516/522444

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

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;
   }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 拖动时跳转 ImageView。 getX() 和 getY() 值正在跳跃

    我创建了一个用于拖动视图的 onTouchListener 如果我使用的话 图像可以顺利拖动getRawX and getRawY 问题是 当您向下放置第二个指针然后抬起第一个指针时 图像将跳转到第二个指针 此 onTouchListene
  • Base36 编码字符串?

    我一直在网上查找 但找不到解决此问题的方法 在 Python Ruby 或 Java 中 如何对以下字符串进行 Base 36 编码 nOrG9Eh0uyeilM8Nnu5pTywj3935kW 5 Ruby 以 36 为基数 s unpa
  • 从 MS Access 中提取 OLE 对象(Word 文档)

    我有一个 Microsoft Access 数据库 其中包含一个包含 Microsoft Word 文档的 OLE 对象字段 我试图找到代码来检索保存在 OLE 对象中的文件 以便用户可以从我的 JavaFx 应用程序中的按钮下载它 但没有
  • Logback:SizeAndTimeBasedRollingPolicy 不遵守totalSizeCap

    我正在尝试以一种方式管理我的日志记录 一旦达到总累积大小限制或达到最大历史记录限制 我最旧的存档日志文件就会被删除 当使用SizeAndTimeBasedRollingPolicy在 Logback 1 1 7 中 滚动文件追加器将继续创建
  • 您建议使用哪种压缩(GZIP 是最流行的)servlet 过滤器?

    我正在寻找一个用于大容量网络应用程序的 GZIP servlet 过滤器 我不想使用容器特定的选项 要求 能够压缩响应负载 XML Faster 已在大批量应用的生产中得到验证 应适当设置适当内容编码 跨容器移植 可选择解压缩请求 谢谢 我
  • 如何通过注解用try-catch包装方法?

    如果应该在方法调用中忽略异常 则可以编写以下内容 public void addEntryIfPresent String key Dto dto try Map
  • 从直方图计算平均值和百分位数?

    我编写了一个计时器 可以测量任何多线程应用程序中特定代码的性能 在下面的计时器中 它还会在地图中填充花费了 x 毫秒的调用次数 我将使用这张图作为我的直方图的一部分来进行进一步的分析 例如调用花费了这么多毫秒的百分比等等 public st
  • 从休眠乐观锁定异常中恢复

    我有一个这样的方法 Transactional propagation Propagation REQUIRES NEW public void doSomeWork Entity entity dao loadEntity do some
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 如何从日期中删除毫秒、秒、分钟和小时[重复]

    这个问题在这里已经有答案了 我遇到了一个问题 我想比较两个日期 然而 我只想比较年 月 日 这就是我能想到的 private Date trim Date date Calendar calendar Calendar getInstanc
  • 在 Clojure 中解压缩 zlib 流

    我有一个二进制文件 其内容由zlib compress在Python上 有没有一种简单的方法可以在Clojure中打开和解压缩它 import zlib import json with open data json zlib wb as
  • Lombok @Builder 不创建不可变对象?

    在很多网站上 我看到 lombok Builder 可以用来创建不可变的对象 https www baeldung com lombok builder singular https www baeldung com lombok buil
  • Android 标记如何实现拖放?

    你好 我正在 Android 中开发 MapView 应用程序 我有三个标记 我希望稍后能够使用 Google Map API getlocation function 为了尝试一下 我想使用拖放功能移动标记 然后检查位置 任何人都可以通过
  • 禁用 Android 菜单组

    我尝试使用以下代码禁用菜单组 但它不起作用 菜单项仍然启用 你能告诉我出了什么问题吗 资源 菜单 menu xml menu menu
  • 如何在Java中对对象数组进行字段级别排序以进行等级比较?

    In Java Class StudentProgress String Name String Grade CTOR goes here main class main method StudentProgress arrayofObje
  • JMS 中的 MessageListener 和 Consumer 有什么区别?

    我是新来的JMS 据我了解Consumers能够从队列 主题中挑选消息 那么为什么你需要一个MessageListener因为Consumers会知道他们什么时候收到消息吗 这样的实际用途是什么MessageListener 编辑 来自Me
  • 源值 1.5 的错误已过时,将在未来版本中删除

    我使用 scala maven plugin 来编译包含 scala 和 java 代码的项目 我已经将源和目标设置为1 7 但不知道为什么maven仍然使用1 5 这是我在 pom xml 中的插件
  • ECDH使用Android KeyStore生成私钥

    我正在尝试使用 Android KeyStore Provider 生成的私有文件在 Android 中实现 ECDH public byte ecdh PublicKey otherPubKey throws Exception try
  • HttpClient请求设置属性问题

    我使用这个 HttpClient 库玩了一段时间 几周 我想以某种方式将属性设置为请求 不是参数而是属性 在我的 servlet 中 我想使用 Integer inte Integer request getAttribute obj 我不
  • 即使调整大小,如何获得屏幕的精确中间位置

    好的 这个问题有两部分 当我做一个JFrame 并在其上画一些东西 即使我将宽度设置为 400 并使其在一个项目击中它时 当然 允许项目宽度 它会反弹回来 但由于某种原因 它总是偏离屏幕约 10 个像素 有没有办法解决这个问题 或者我只需要

随机推荐

  • 在 Python 中使用 Re 删除双空格/制表符组合

    我想使用 Re 模块将 Python 中存在连续制表符和 或空格的所有实例替换为单个空格 我不想删除新行 这排除了 s 推荐 目前我有 formateed string re sub t formateed string formateed
  • 如何使用流获取嵌套集合中的所有元素

    我有一个包含不同嵌套集合的类 现在我想接收嵌套集合的所有元素 具体我想收集集合的所有 StrokePoints 我可以用 旧 java解决它 但如何用流来解决它 int strokesCounter 0 List
  • 名为“DefaultApi”的路由已在路由集合中

    这个问题可能看起来重复 但这略有不同 在所有其他问题中 我注意到他们注册了多条路线 但就我而言 我只有一条路线 我正在创建 asp net webapi framework 4 5 并且在 RegisterRoutes 方法中只有一条路由
  • 在本地找不到元数据

    在本地机器上 我安装了一个带有 Maven 存储库的 Artifactory 并且我的项目有一个非常简单的 pom 文件 它指向它
  • 在安全的 Android 锁屏中使用 FLAG_SHOW_WHEN_LOCKED 和 disableKeyguard()

    上下文 最近 我一直在寻找可靠的方法来控制安全的 Android Keyguard 主要是显示自定义锁屏 我知道谷歌已经声明自定义锁屏不受该平台的正式支持 并且应该预料到事情会被破坏 但是 利用现有的 API 我相信一定有办法做到这一点 我
  • Linux 下 C 语言的公钥实现

    我正在尝试使用公钥加密来签名并稍后验证文件 该文件是一个简单的纯文本文件 其中包含用于创作目的的用户信息 我尝试了不同的站点来实现公钥加密算法的 C 实现 但我没有找到任何东西 许多网站都指出使用证书 x 509 等 但这远远超出了我的需要
  • 如何使用带有变量表名称和条件的立即执行

    我想创建一个 PL SQL 函数 该函数传递一个表名和一个条件 并返回该表上满足条件的行数 我创建了这个函数 CREATE OR REPLACE FUNCTION CHECK EXISTS TABLE NAME VARCHAR2 CONDI
  • 如何删除除最后五个之外的所有 Git 提交

    我有一个非常大的 Git 存储库 其中仅包含经常更改的二进制文件 当然 Git 存储库是much比其中的实际文件大 我并不真正关心旧的历史记录 我只需要一些较新的历史记录就能够恢复一些错误的更改 假设我想删除除最后五个之外的所有提交 当然
  • Dockerized Node js 应用程序无法启动

    在对我的演示 Express js 应用程序进行 Docker 化并启动容器后 由于以下原因我无法访问该服务 Connection Timeout dockerized 之前的 for 项目的 URL 产生了 Hello world 在浏览
  • 通过相对路径查找外部测试文件进行单元测试 c++ cmake guest

    访问 C 项目单元测试的外部测试文件的正确方法是什么 我正在使用 CMake 和 Gtest 这是目录结构的示例 Project src test unit tests here test data data file here Thank
  • 从ortools获取SAT解决方案列表

    我正在尝试找出如何从以下位置获取可能解决方案的完整列表ortools sat python cp model 我知道我可以打印它们 如下例所示 但我不清楚如何获取这些值 例如作为嵌套列表或字典列表 我尝试通过修改来编写自己的回调类VarAr
  • “创建数据库权限被拒绝”错误

    我在安装了 Windows XP 操作系统的系统上安装了 SQL SERVER 2008 R2 每当我尝试创建新数据库时 它都会显示错误 CREATE DATABASE PERMISSION DENIED IN DATABASE maste
  • echo 在 bash 脚本中输出 -e 参数。我怎样才能防止这种情况发生?

    我读过关于 echo 的手册页 它告诉我 e 参数将允许转义字符 例如换行符的转义 n 具有其特殊含义 当我输入命令时 echo e foo nbar 进入交互式 bash shell 我得到了预期的输出 foo bar 但是当我使用相同的
  • Android css 字体大小 vw vh 响应式替代方案

    安卓上有替代方案吗 我知道我可以为每个屏幕密度和尺寸创建样式文件并在那里更改字体大小 但是提供单一相对 自动可缩放值 就像在 CSS 中那样 会很棒 我很惊讶 Android 没有它 并且 svg 可绘制对象仅在最新的 api 中支持 谢谢
  • 动态创建字段的 Jquery 验证

    我有基本的 javascript 代码来生成输入文本区域 如下所示 btnAdd click function e var itemIndex container input iHidden length e preventDefault
  • 使用不同结合性和相同优先级的相邻运算符消除表达式的歧义

    假设我有一个如下表达式 其中 and 是具有相同优先级但不同结合性的二元运算符 x y z Would y属于 or 并基于什么标准 根据 Edsgar Dijkstra 的调车场算法 http en wikipedia org wiki
  • PHPMailer 发生致命错误

    我正在尝试使用 PHPMailer 通过 gmail SMTP 服务器发送邮件 但出现致命错误 并且找不到任何解决方案 我的 php 文件
  • C++/CLI:为什么我不能通过引用传递字符串?

    为什么 Microsoft 的 C CLI 不允许我通过引用传递字符串 我收到以下错误 C3699 无法在类型 System String 上使用此间接寻址 首先 NET 实际上有两种 Microsoft 特定的 C 方言 较旧的 托管 C
  • ORMLite - 查询外域

    使用 Android 版 ORMLite 我需要构建一个按订单 ID 或客户名称返回订单的查询 请考虑以下类声明 DatabaseTable tableName order public class Order DatabaseField
  • Java:如何将控件而不是其数据拖放到新位置?

    在Java中 当拖动的项目是源控件本身时 执行拖放的最佳方法是什么 我知道控件也只不过是数据 但差异确实会影响 UI 我正在创建一个纸牌风格的游戏 其中有从 JLabel 派生的 Card 类的卡片对象 我想将该卡拖放到另一个位置 方法是将