0

该程序是在屏幕上创建汽车和/或卡车图标的动画。我现在拥有它的方式无法正常工作。具体来说,该程序没有单击并向右拖动。如果一个对象没有被选中,一旦点击,它会变得更粗,表明它被选中。从那里我们希望能够拖动它,程序将在鼠标所在的任何地方重绘图像。如果图像未选中,当我单击并拖动它时,它可以正常工作。我遇到的问题是图像是否已被选中。如果图像已经被选中,当我将鼠标移到它上面并单击它以将其移动到不同的位置时,它不会移动,而是取消选择,因此不会发生移动。这是 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();
      }
   });

有人可以帮我解释一下是什么导致程序在我拖动而不是移动它时取消选择已选择的图像以及如何解决这个问题?谢谢。

4

1 回答 1

1

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

它确实需要您维护有关当前和先前状态的一些信息,以便您知道对象是刚刚被选中还是先前被选中,但基本思想很有效。

拉我一把

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();
        }

    }

}

我只是迷路了。我正在查看所有这些代码,甚至不明白它在做什么。

是的,我对我的代码有很多这样的感觉。

基本上...

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

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

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

清如泥:P

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

于 2015-10-28T23:35:12.810 回答