如何在不取消选择的情况下单击并拖动某些东西 [英] How to click and drag something without it deselecting

查看:88
本文介绍了如何在不取消选择的情况下单击并拖动某些东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The program is an animation that creates a car and/or truck icon on the screen. The way I have it now it isn't working correctly. Specifically, the program is not clicking and dragging right. If one object is not-selected, once clicked on, it will become bolder to show that it is selected. From there we want to be able to drag it and the program will redraw the image wherever the mouse goes. If the image is un-selected, when I click and drag it, it works fine. The problem I am having is if the image is already selected. If the image is already selected, when I move the mouse over to it and click on it in order to move it to a different position, instead of moving, it is deselected instead so no movement occurs. Here is the code for the mousePressed and mouseDragged events. I think that is where the problem is, but I'm not sure what is causing it.

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

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

Can someone help explain to me what is causing the program to deselect an already selected image when I drag it instead of moving it and how to fix this problem? Thanks.

推荐答案

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

One of the side effects of a drag operation is the fact that mouseClicked won't be called. Why is this important? Basically you can use this fact to make a decision about whether a object should be deselected or not within the mouseClicked event instead of something like mousePressed or mouseReleased.

它确实需要您维护有关当前状态和先前状态的一些信息,因此您知道对象是刚刚被选中还是先前已被选中,但是基本思路很好.

It does require you to maintain some information about the current and previous states, so you know whether the object was just selected or was previously selected, but the basic idea works well.

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

    }

}

我真迷失了.我正在查看所有这些代码,甚至不了解它在做什么.

I am just so lost. I am looking at all this code and don't even understand what it is doing.

是的,我对我的代码非常满意.

Yeah, I feel like this about my code a lot.

基本上...

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

First: mousePressed is called, I reverse my list of objects, because the top most component will be the last in the list (this is my requirement), I store the currently selected object in the previous variable, I use this to determine if there has been a change in selection or not. I check to see if the user clicked the selected object or not, if they did, we can basically skip every thing else. If not, we determine what they clicked, if anything. The delta is simply the difference between the place they clicked and the location of the object, this is used to make the drag more natural

如果没有拖动发生: mouseClicked.我们测试以查看selected对象是否等于previous对象,以及是否在selected对象中单击了鼠标(如果它们是true),则应取消选择当前的selected对象.否则,用户基本上只是更改了选择,因此我们不想立即取消选择它.

If no drag occurs: mouseClicked is called. We test to see if the selected object is equal to the previous object and if the mouse was clicked within the selected object, if these are true, then the currently selected object should be deselected. Otherwise the user has basically just changed the selection, so we don't want to immediately deselect it.

否则发生拖动: mouseDragged.我们只是检查一下是否是selected,我们计算当前鼠标位置和点击偏移量"之间的差,并更新selected对象的位置

Else if a drag occurs: mouseDragged is called. We simply check to see if something is selected, we calculate the difference between the current mouse position and the "click offset" and update the position of the selected object

清除为泥浆:P

还要记住的一件事是,即使mouseClicked不是(在没有拖动的情况下在mouseReleased之后调用),也会总是在mousePressed之后调用mouseReleased.

One thing to also remember is mouseReleased will always be called after mousePressed, even if mouseClicked isn't (which is called after mouseReleased when no dragging occurs).

这篇关于如何在不取消选择的情况下单击并拖动某些东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆