【问题标题】:Java Swing - Drag & Drop drawString textJava Swing - 拖放 drawString 文本
【发布时间】:2012-03-17 13:13:13
【问题描述】:

我已经四处寻找这个问题,但找不到答案......

我目前有一个 JPanel,我正在使用 Graphics2D g2.drawString() 方法在其中绘制大量 unicode 字符(音乐笔记)。

我有一个ArrayListKeyPress 对象,每个对象都包含一个或多个g2.drawString() 调用。

所以每个KeyPress 对象都是一个音符,并绘制在 JPanel 上。

我将如何添加功能以使用户能够选择和拖动对象?

【问题讨论】:

  • 我不太确定这是一个真正的拖放问题(使用拖放数据传输支持的问题),但我觉得更有可能是一个简单的 MouseListener-click on and拖动屏幕图形或精灵类型问题。那么,你尝试过什么?你熟悉使用 MouseListeners 和 MouseMotionListeners 吗?
  • 我尝试过拖动矩形和其他带边界形状的示例,但我不知道如何判断鼠标单击是否在字符串区域内。

标签: java string swing drag-and-drop


【解决方案1】:

为什么不把你的字符串放在 JLabels 中,然后简单地拖动它们...

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class DragLabelEg {
   private static final String[] LABEL_STRINGS = { "Do", "Re", "Me", "Fa",
         "So", "La", "Ti" };
   private static final int HEIGHT = 400;
   private static final int WIDTH = 600;
   private static final Dimension MAIN_PANEL_SIZE = new Dimension(WIDTH, HEIGHT);
   private static final int LBL_WIDTH = 60;
   private static final int LBL_HEIGHT = 40;
   private static final Dimension LABEL_SIZE = new Dimension(LBL_WIDTH,
         LBL_HEIGHT);
   private JPanel mainPanel = new JPanel();
   private Random random = new Random();

   public DragLabelEg() {
      mainPanel.setPreferredSize(MAIN_PANEL_SIZE);
      mainPanel.setLayout(null);

      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      for (int i = 0; i < LABEL_STRINGS.length; i++) {
         JLabel label = new JLabel(LABEL_STRINGS[i], SwingConstants.CENTER);
         label.setSize(LABEL_SIZE);
         label.setOpaque(true);
         label.setLocation(random.nextInt(WIDTH - LBL_WIDTH),
               random.nextInt(HEIGHT - LBL_HEIGHT));
         label.setBackground(new Color(150 + random.nextInt(105), 150 + random
               .nextInt(105), 150 + random.nextInt(105)));
         label.addMouseListener(myMouseAdapter);
         label.addMouseMotionListener(myMouseAdapter);

         mainPanel.add(label);
      }
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

   private class MyMouseAdapter extends MouseAdapter {
      private Point initLabelLocation = null;
      private Point initMouseLocationOnScreen = null;

      @Override
      public void mousePressed(MouseEvent e) {
         JLabel label = (JLabel) e.getSource();
         // get label's initial location relative to its container
         initLabelLocation = label.getLocation();

         // get Mouse's initial location relative to the screen
         initMouseLocationOnScreen = e.getLocationOnScreen();
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         initLabelLocation = null;
         initMouseLocationOnScreen = null;
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         // if not dragging a JLabel
         if (initLabelLocation == null || initMouseLocationOnScreen == null) {
            return;
         }
         JLabel label = (JLabel) e.getSource();

         // get mouse's new location relative to the screen
         Point mouseLocation = e.getLocationOnScreen();

         // and see how this differs from the initial location.
         int deltaX = mouseLocation.x - initMouseLocationOnScreen.x;
         int deltaY = mouseLocation.y - initMouseLocationOnScreen.y;

         // change label's position by the same difference, the "delta" vector
         int labelX = initLabelLocation.x + deltaX;
         int labelY = initLabelLocation.y + deltaY;

         label.setLocation(labelX, labelY);
      }
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createGui();
         }
      });
   }

   private static void createGui() {
      JFrame frame = new JFrame("App");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new DragLabelEg().getMainPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }
}

【讨论】:

  • 我认为作者可能想选择一堆“标签”然后一起移动,在这种情况下,鼠标按下,鼠标移动事件需要测试我们是否有任何“选定项”与否
【解决方案2】:

请参阅supporting user interaction. 上的教程。它归结为确定单击并按住鼠标时哪些(如果有)对象位于鼠标下方。在拖动事件中,移动选定的对象并重新绘制画布。

可以通过FontMetrics获取字符串的边界:

String text = "Hello world!";
Rectangle2D bounds = g2.getFontMetrics().getStringBounds(text, g2);

我假设左上角的矩形是 (0, 0),所以你需要添加 (x, y) 到它(其中 x, y 是你传递给 drawString 的参数)。

【讨论】:

  • 谢谢,但是如何获得字符串的边界?
  • 感谢更新,目前我正在翻译'bounds'矩形,有没有办法设置矩形的坐标?
  • 我将创建一个新的 Rectangle2D.Double,其中 x 和 y 设置为发送到 drawString 的坐标,w 和 h 设置为 FontMetrics 返回的边界矩形的宽度和高度。
  • 感谢您的帮助!我现在已经设法拖放笔记了 :) 最后一个问题,我将如何拖动它以使其捕捉到某些坐标?
  • 不要将文本移动到拖动事件发生的确切位置,而是将其移动到您想要捕捉到的最近点。编写一个函数,返回给定拖动事件位置最近的此类点。
【解决方案3】:

这个example 展示了一种选择多个对象的方法,使用键盘或鼠标,然后拖动 他们作为一个群体。它操纵任意节点而不是字形,但您可能会发现它很有启发性。

【讨论】:

    猜你喜欢
    • 2015-12-29
    • 2017-04-27
    • 2013-07-19
    • 1970-01-01
    • 2011-12-08
    • 2012-03-28
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多