判断是否单击到UI及拖动UI控件的两种方法

1 篇文章 0 订阅

游戏中有许多单击操作 很多时候要区分普通单击和单击到UI的操作

private void Update()
    {
        if (Input.GetMouseButton(0)) 
        {
            if (EventSystem.current.IsPointerOverGameObject() || GUIUtility.hotControl != 0) 
            {
                Debug.Log("单击到UI");
            }
            else
            {
                Debug.Log("没有单击到UI");
            }
        }
    }

在窗口端进行判断时使用: 

EventSystem.current.IsPointerOverGameObject()方法,作用:判断鼠标是否点击在UI

GUIUtility.hotControl = id;

为每个GUI分配一个ControlID,此ID使每个GUI独立,如果没有正确分配这个ID,你最终会遇到多个GUI操作的冲突.在用OnGUI函数绘制窗体时,鼠标在窗体或控件上面操作时,场景则不应该响应鼠标事件。网上一般用 GUIUtility.hotcontrol!=0来屏蔽,当hotControl不为0时说明有控件处于激活状态。查官方文档,当鼠标在GUI控件上面按下时,hotcontrol被设置为该控件的ID,当鼠标按键被弹起时,hotcontrol为设置为0,因为在场景里面只能配合鼠标按下事件,不能配合鼠标弹起,因为此时hotcontrol已经被引擎置为0了。 但是目前开发的界面上发现,偶尔在窗体上点击时,hotcontrol仍然为0,因此不能完全屏蔽掉GUI的操作。不知道有人知道什么原因么?现在只好做一个全局标记变量,每个界面负责管理这个变量,当鼠标在某个界面内,则把标记置为true。离开或界面被关闭,则置为false。

新建一个背景图,以其为父物体,再建两个都是Image的子物体.我们将拖动左边的物体和右边的物体重合.两种方法,一个是用触发系统,繁琐,一个用Unity封装好的接口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragTest1 : MonoBehaviour
{
    private RectTransform dragArea;//拖动区域
    private Image imageDrag;//拖动图像
    private Image imageTarget;//目标区域

    private void Awake()
    {
        dragArea = GameObject.Find("RawImage").GetComponent<RectTransform>();
        imageDrag = transform.Find("Image Target").GetComponent<Image>();
        imageTarget = transform.Find("Image Drag").GetComponent<Image>();
    }
    void Start()
    {
        EventTrigger trigger = imageDrag.gameObject.AddComponent<EventTrigger>();
        EventTrigger.Entry dragentry = new EventTrigger.Entry();
        dragentry.eventID = EventTriggerType.Drag;//创建一个拖动事件
        dragentry.callback = new EventTrigger.TriggerEvent();
        dragentry.callback.AddListener(delegate (BaseEventData eventData)
        {
            Vector2 touchpos = ((PointerEventData)eventData).position;//获得当前拖动的屏幕坐标
            Vector2 uguiPos;
            //将屏幕坐标转换为UGUI的本地坐标
            bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(dragArea, touchpos, ((PointerEventData)eventData).enterEventCamera, out uguiPos);
            //如果拖动位置在区域内
            if (isRect && RectTransformUtility.RectangleContainsScreenPoint(dragArea,touchpos,((PointerEventData)eventData).enterEventCamera))
            {
                //更新被拖动图象的位置
                imageDrag.rectTransform.localPosition = uguiPos;
            }
            //拖动的时候防止阻挡射线检测
            imageDrag.raycastTarget = false;
        });

        EventTrigger.Entry enddragentry = new EventTrigger.Entry();
        enddragentry.eventID = EventTriggerType.EndDrag;//结束拖动事件
        enddragentry.callback = new EventTrigger.TriggerEvent();
        enddragentry.callback.AddListener(delegate (BaseEventData eventData)
        {
            var go = ((PointerEventData)eventData).pointerEnter;
            //如果拖动到目标位置
            if (go != null && go.name.CompareTo("image Target") == 0) 
            {
                imageDrag.rectTransform.position = imageTarget.rectTransform.position;
            }
            imageDrag.raycastTarget = true;
        });
        trigger.triggers.Add(dragentry);
        trigger.triggers.Add(enddragentry);
    }
    //private void Update()
    //{
    //    if (Input.GetMouseButton(0)) 
    //    {
    //        if (EventSystem.current.IsPointerOverGameObject() || GUIUtility.hotControl != 0) 
    //        {
    //            Debug.Log("单击到UI");
    //        }
    //        else
    //        {
    //            Debug.Log("没有单击到UI");
    //        }
    //    }
    //}
}

这里的代码主要是触发了两个事件 一个是拖动事件:dragentry.eventID = EventTriggerType.Drag;

一个是结束拖动的事件:enddragentry.eventID = EventTriggerType.EndDrag;

在拖动事件中 获取到屏幕坐标位置 并将屏幕坐标转换为UGUi的本地坐标 实现拖动效果;在拖动结束后 判断是否拖动到目标位置并更新位置

首先 创建一个类 继承接口IDragHandler IEndDragHandler接口 实现他们的接口方法

即可获得拖动后的位置 这个类要被挂到被拖动的UI控件上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;//事件系统

public class DragImage : MonoBehaviour, IDragHandler, IEndDragHandler
{
    public System.Action<PointerEventData> onDragEvent;//委托拖拽事件回调
    public System.Action<PointerEventData> onDragEndEvent;//委托拖曳结束事件回调
    public void OnDrag(PointerEventData eventData)
    {
        if (onDragEvent != null)
        {
            onDragEvent(eventData);//响应开始拖曳
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (onDragEndEvent != null)
        {
            onDragEndEvent(eventData);//响应结束拖曳
        }
    }
}

创建脚本 大致和上一种拖曳方法一样

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragTest2 : MonoBehaviour
{
    private RectTransform dragArea;
    public DragImage imageDrag;//继承拖曳接口
    private Image imageTarget;
    private void Awake()
    {
        dragArea = GameObject.Find("RawImage").GetComponent<RectTransform>();
        imageTarget = dragArea.Find("Image Target").GetComponent<Image>();
    }
    private void Start()
    {
        imageDrag.onDragEvent += (PointerEventData eventData) =>
        {
            Vector2 touchPos = eventData.position;//获得当前拖动的屏幕坐标位置
            Vector2 uguiPos;
            bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(dragArea, touchPos, eventData.enterEventCamera, out uguiPos);
            if (isRect && RectTransformUtility.RectangleContainsScreenPoint(dragArea, touchPos, eventData.enterEventCamera)) 
            {
                imageDrag.GetComponent<RectTransform>().localPosition = uguiPos;
                imageDrag.GetComponent<Image>().raycastTarget = false;
            }
        };
        imageDrag.onDragEndEvent+=(PointerEventData eventData)=>{
            var go = ((PointerEventData)eventData).pointerEnter;
            if (go != null && go.name.CompareTo("image Target") == 0) 
            {
                imageDrag.GetComponent<RectTransform>().position = imageTarget.rectTransform.position;
            }
            imageDrag.GetComponent<Image>().raycastTarget = true;
        };
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果你想将新窗口的.ui文件中的控件拖拽到QWidget类的头文件中,并定义控件的成员变量,可以按照以下步骤进行: 1. 首先打开Qt Creator,创建一个新的QWidget类,然后在该类的头文件中包含以下代码: ``` #include <QWidget> #include "ui_NewWindow.h" class NewWindow : public QWidget { Q_OBJECT public: explicit NewWindow(QWidget *parent = nullptr); private: Ui::NewWindow ui; }; ``` 2. 接着,在Qt Creator的“项目”面板中,双击新窗口的.ui文件以打开它。然后,从左侧的“窗口组件”面板中拖动需要的控件到新窗口的设计界面上。 3. 在设计界面上选择一个控件,然后在“对象查看器”中找到它,并右键单击它。在弹出的菜单中,选择“提升为...”选项。 4. 在“提升为”对话框中,选择“QWidget”作为基类,并将类名设置为“Ui::NewWindow”。然后,单击“添加”按钮并关闭对话框。 5. 回到新窗口的.ui文件中,右键单击设计界面上的控件,并选择“转换为...”选项。在弹出的对话框中,选择相应的控件类型并单击“确定”。 6. 接着,将新窗口的.ui文件中的所有控件都转换为相应的控件类型。然后,保存并关闭新窗口的.ui文件。 7. 回到新窗口的头文件中,将以下代码添加到构造函数的实现中,以初始化所有控件: ``` NewWindow::NewWindow(QWidget *parent) : QWidget(parent), ui(new Ui::NewWindow) { ui->setupUi(this); } ``` 8. 最后,在新窗口的头文件中,为每个控件定义一个成员变量,例如: ``` private: Ui::NewWindow ui; QPushButton *m_button; ``` 9. 完成上述步骤后,你就可以在新窗口的代码中使用这些控件了。例如,可以在构造函数中设置按钮的文本: ``` m_button = ui->pushButton; m_button->setText("Click me!"); ``` ### 回答2: 在Qt中,我们可以通过以下步骤将新窗口的.ui文件中的控件拖拽到QWidget类的头文件中,并定义控件的成员变量: 1. 首先,打开新窗口的.ui文件,在Qt的设计视图中找到需要拖拽的控件。 2. 在设计视图中,选择需要拖拽的控件,然后点击鼠标左键不放,在新窗口的QWidget类的头文件中找到合适的位置松开鼠标左键。 3. 在弹出的对话框中,选择“提升为...”选项。 4. 在对话框中,选择“QWidget”为基类,并填写自定义类的名称。点击“添加”按钮。 5. 点击“全局替换”按钮,将新窗口中的控件替换为自定义的类。 6. 在QWidget类的头文件中,会生成一个新的成员变量,以及与控件相关的操作函数。 例如,如果在.ui文件中拖拽了一个QPushButton控件,并按照上述步骤进行了提升,那么在QWidget类的头文件中会生成以下代码: ```cpp private: QPushButton *pushButton; // 定义控件的成员变量 public: explicit MyWidget(QWidget *parent = nullptr); ~MyWidget(); private slots: void on_pushButton_clicked(); // 控件的点击事件槽函数 ``` 通过以上步骤,我们成功将新窗口的.ui文件中的控件拖拽到QWidget类的头文件中,并在头文件中定义了控件的成员变量。这样我们就可以在代码中方便地访问控件,并对其进行操作。 ### 回答3: 要将新窗口的.ui文件中的控件拖拽到QWidget类的头文件中,并定义控件的成员变量,可以按照以下步骤进行操作。 1. 首先,在Qt Creator中打开该.ui文件。选择"设计"视图,点击左侧的"小部件"按钮或者直接在工具箱中选择控件。 2. 在设计视图中,拖拽需要添加到QWidget类的控件到窗体中。 3. 打开QWidget类的头文件,可以使用Qt Creator的"编辑"视图打开,或手动在项目文件浏览器中找到该文件并打开。 4. 在头文件中找到类的私有部分,即私有段(private),或者在类的公有部分(public)添加新的私有段。 5. 将QWidget类的头文件窗口切换到"设计"视图,选择新添加的控件,拖拽该控件到头文件私有段中,并放置在中括号{}中。 6. 在头文件私有段中,控件被拖拽后会自动生成成员变量的代码。可以根据需要对默认生成的变量名进行修改。 7. 根据需要对控件的属性和信号槽进行设置,例如设置控件的名称、大小、位置、样式、信号槽等。 8. 最后,对QWidget类的头文件进行保存。 通过上述步骤,将新窗口的.ui文件中的控件拖拽到QWidget类的头文件中,并定义了控件的成员变量。这样可以在代码中轻松地调用和操作这些控件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值