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:如何将控件而不是其数据拖放到新位置? 的相关文章

  • 如何将本机库链接到 IntelliJ 中的 jar?

    我正在尝试在 IntelliJ 中设置 OpenCV 但是我一直在弄清楚如何告诉 IntelliJ 在哪里可以找到本机库位置 在 Eclipse 中 添加 jar 后 您可以在 Build Config 屏幕中设置 Native 库的位置
  • 如何让 BlazeDS 忽略属性?

    我有一个 java 类 它有一个带有 getter 和 setter 的字段 以及第二对 getter 和 setter 它们以另一种方式访问 该字段 public class NullAbleId private static final
  • 不同帐户上的 Spring Boot、JmsListener 和 SQS 队列

    我正在尝试开发一个 Spring Boot 1 5 应用程序 该应用程序需要侦听来自两个不同 AWS 帐户的 SQS 队列 是否可以使用 JmsListener 注解创建监听器 我已检查权限是否正确 我可以使用 getQueueUrl 获取
  • Junit:如何测试从属性文件读取属性的方法

    嗨 我有课ReadProperty其中有一个方法ReadPropertyFile返回类型的Myclass从属性文件读取参数值并返回Myclass目的 我需要帮助来测试ReadPropertyFile方法与JUnit 如果可能的话使用模拟文件
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • 过滤两次 Lambda Java

    我有一个清单如下 1 2 3 4 5 6 7 和 预期结果必须是 1 2 3 4 5 6 7 我知道怎么做才能到7点 我的结果 1 2 3 4 5 6 我也想知道如何输入 7 我添加了i gt i objList size 1到我的过滤器
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • Java 公历日历更改时区

    我正在尝试设置 HOUR OF DAY 字段并更改 GregorianCalendar 日期对象的时区 GregorianCalendar date new GregorianCalendar TimeZone getTimeZone GM
  • java.lang.IllegalStateException:应用程序 PagerAdapter 更改了适配器的内容,而没有调用 PagerAdapter#notifyDataSetChanged android

    我正在尝试使用静态类将值传递给视图 而不是使用意图 因为我必须传递大量数据 有时我会收到此错误 但无法找出主要原因是什么 Error java lang IllegalStateException The application s Pag
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • Android:无法使用 DbHelper 和 Contract 类将数据插入 SQLite

    public class Main2Activity extends AppCompatActivity private EditText editText1 editText2 editText3 editText4 private Bu
  • Eclipse 启动时崩溃;退出代码=13

    I am trying to work with Eclipse Helios on my x64 machine Im pretty sure now that this problem could occur with any ecli

随机推荐

  • 在 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 类的卡片对象 我想将该卡拖放到另一个位置 方法是将