如何点击并拖动没有它的内容取消选择

时间:2015-10-28 22:07:22

标签: java animation mouseevent mousemotionlistener

该程序是一个动画,可在屏幕上创建汽车和/或卡车图标。我现在的方式是它无法正常工作。具体来说,程序没有单击并向右拖动。如果未选择一个对象,则一旦单击该对象,将显示更大胆以显示它已被选中。从那里我们希望能够拖动它,程序将重绘鼠标所在的任何地方。如果图像未被选中,当我单击并拖动它时,它可以正常工作。我遇到的问题是图像是否已被选中。如果已经选择了图像,当我将鼠标移动到它并单击它以将其移动到不同的位置而不是移动时,它会被取消选择,因此不会发生移动。以下是mousePressed和mouseDragged事件的代码。我认为这就是问题所在,但我不确定是什么原因造成的。

addMouseListener(new
   MouseAdapter()
   {
      public void mousePressed(MouseEvent event)
      {
         mousePoint = event.getPoint();
         for (SceneShape s : shapes)
         {
            if (s.contains(mousePoint))
               s.setSelected(!s.isSelected());
         }
         repaint();
      }
   });

addMouseMotionListener(new
   MouseMotionAdapter()
   {
      public void mouseDragged(MouseEvent event)
      {
         Point lastMousePoint = mousePoint;
         mousePoint = event.getPoint();
         for (SceneShape s : shapes)
         {
            if (s.isSelected())
            {
               double dx
                     = mousePoint.getX() - lastMousePoint.getX();
               double dy
                     = mousePoint.getY() - lastMousePoint.getY();
               s.translate((int) dx, (int) dy);
            }
         }
         repaint();
      }
   });

当我拖动它而不是移动它以及如何解决这个问题时,有人可以帮我解释导致程序取消选择已经选择的图像的原因吗?感谢。

1 个答案:

答案 0 :(得分:1)

拖动操作的一个副作用是不会调用mouseClicked。为什么这很重要?基本上,您可以使用此事实来决定是否应在mouseClicked事件中取消选择对象,而不是mousePressedmouseReleased

它确实需要您维护有关当前和以前状态的一些信息,因此您知道该对象是刚刚被选中还是之前被选中,但基本想法效果很好。

Drag me

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class WhatADrag {

    public static void main(String[] args) {
        new WhatADrag();
    }

    public WhatADrag() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Rectangle> boxes;
        private Rectangle selected;

        public TestPane() {
            boxes = new ArrayList<>(25);
            int x = 0;
            int y = 0;
            for (int index = 0; index < 10; index++) {
                boxes.add(new Rectangle(x, y, 100, 100));
                x += 25;
                y += 25;
            }

            MouseAdapter ma = new MouseAdapter() {

                private Rectangle previous;
                private Point delta;

                @Override
                public void mousePressed(MouseEvent e) {
                    List<Rectangle> reversed = new ArrayList<>(boxes);
                    Collections.reverse(reversed);
                    previous = selected;
                    if (selected == null || !selected.contains(e.getPoint())) {
                        for (Rectangle box : reversed) {
                            if (box.contains(e.getPoint())) {
                                selected = box;
                                delta = new Point(e.getX() - selected.x, e.getY() - selected.y);
                                repaint();
                                break;
                            }
                        }
                        if (selected != null) {
                            boxes.remove(selected);
                            boxes.add(boxes.size() - 1, selected);
                        }
                    } else if (selected != null) {
                        delta = new Point(e.getX() - selected.x, e.getY() - selected.y);
                    }
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    if (selected == previous && selected != null && selected.contains(e.getPoint())) {
                        selected = null;
                        repaint();
                    }
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    if (selected != null) {
                        int x = e.getX() - delta.x;
                        int y = e.getY() - delta.y;
                        selected.x = x;
                        selected.y = y;
                        repaint();
                    }
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

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

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (Rectangle box : boxes) {
                if (box != selected) {
                    g2d.setColor(Color.BLUE);
                    g2d.fill(box);
                    g2d.setColor(Color.BLACK);
                    g2d.draw(box);
                }
            }
            if (selected != null) {
                g2d.setColor(Color.CYAN);
                g2d.fill(selected);
                g2d.setColor(Color.BLUE);
                g2d.draw(selected);
            }
            g2d.dispose();
        }

    }

}
  

我很丢失。我正在查看所有这些代码,甚至不了解它在做什么。

是的,我觉得我的代码很多。

基本上...

首先: mousePressed被调用,我反转我的对象列表,因为最顶层的组件将是列表中的最后一个(这是我的要求),我存储了当前的previous变量中的所选对象,我用它来确定选择是否有变化。我检查用户是否点击了selected对象,如果有,我们基本上可以跳过其他所有内容。如果没有,我们确定他们点击了什么,如果有的话。 delta只是他们点击的地方和对象的位置之间的差异,这用于使拖动更自然

如果没有发生拖动: mouseClicked被调用。我们测试selected对象是否等于previous对象,如果在selected对象中单击鼠标,如果它们是true,那么当前{应取消选择{1}}对象。否则用户基本上只是改变了选择,所以我们不想立即取消选择它。

如果发生拖动,则会调用 selected。我们只是检查是否有mouseDragged,我们计算当前鼠标位置和“点击偏移量”之间的差异并更新selected对象的位置

清除泥浆:P

还要记住的一件事是selected将始终在mouseReleased之后调用,即使mousePressed不是(在mouseClicked之后没有拖动时调用)