You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot 4.2.2中如何检测鼠标悬停窗口时持有的本地文件?

Godot 4.2.2实现拖放悬停时的放置位置提示

要实现文件悬停窗口时显示可放置位置(如VBoxContainer列表项的前后/中间),核心是通过监听拖放输入事件来跟踪鼠标位置,实时计算插入点并显示视觉提示,具体实现步骤如下:

关键实现思路

files_dropped仅在文件放下时触发,悬停阶段需要通过_gui_input捕获InputEventDragDrop事件,结合鼠标位置判断插入位置,再通过临时控件展示视觉提示。

具体代码实现(以VBoxContainer为例)

extends VBoxContainer

var drag_indicator: ColorRect
var is_dragging_files: bool = false

func _ready():
    # 创建拖放位置指示器(可根据需求自定义样式)
    drag_indicator = ColorRect.new()
    drag_indicator.color = Color(0, 0.7, 1)
    drag_indicator.size = Vector2(200, 2)
    drag_indicator.visible = false
    add_child(drag_indicator)
    # 确保容器能接收鼠标事件
    mouse_filter = Control.MOUSE_FILTER_STOP

func _gui_input(event: InputEvent):
    if event is InputEventDragDrop:
        match event.action:
            InputEventDragDrop.DRAG_ENTER:
                # 验证拖入的是文件
                if event.data is Dictionary and event.data.has("files"):
                    is_dragging_files = true
            InputEventDragDrop.DRAG_MOVE:
                if is_dragging_files:
                    update_drop_indicator(event.position)
            InputEventDragDrop.DRAG_EXIT, InputEventDragDrop.DRAG_DROP:
                is_dragging_files = false
                drag_indicator.visible = false

func update_drop_indicator(mouse_pos: Vector2):
    var insert_index = 0
    var child_count = get_child_count()

    # 遍历子节点,判断鼠标对应的插入位置
    for i in range(child_count):
        var child_rect = get_child(i).get_global_rect()
        var child_mid_y = child_rect.position.y + child_rect.size.y / 2
        if mouse_pos.y > child_mid_y:
            insert_index = i + 1
        else:
            break

    # 更新指示器位置
    if child_count == 0:
        drag_indicator.position = to_local(mouse_pos) - Vector2(drag_indicator.size.x/2, 1)
    elif insert_index == 0:
        var first_child_rect = get_child(0).get_global_rect()
        drag_indicator.position = to_local(Vector2(first_child_rect.position.x, first_child_rect.position.y - 1))
    elif insert_index == child_count:
        var last_child_rect = get_child(child_count - 1).get_global_rect()
        drag_indicator.position = to_local(Vector2(last_child_rect.position.x, last_child_rect.position.y + last_child_rect.size.y + 1))
    else:
        var prev_child_rect = get_child(insert_index - 1).get_global_rect()
        drag_indicator.position = to_local(Vector2(prev_child_rect.position.x, prev_child_rect.position.y + prev_child_rect.size.y + 1))

    drag_indicator.visible = true

# 保留原有文件处理逻辑
func _on_files_dropped(files: Array, screen: int) -> bool:
    # 这里可以结合insert_index变量,将文件对应数据插入到列表的指定位置
    # 后续调用Python脚本处理元数据的逻辑不变
    return true

补充说明

  1. 若VBoxContainer嵌套在ScrollContainer中,计算位置时需结合ScrollContainer.scroll_offset修正坐标,避免滚动偏移导致指示器位置错误。
  2. 可自定义指示器样式,比如换成Line控件、带边框的高亮区域,或修改颜色、尺寸适配你的UI风格。
  3. 确保容器的mouse_filter未设置为MOUSE_FILTER_IGNORE,否则无法接收拖放输入事件。

内容的提问来源于stack exchange,提问作者ionarn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:01:14