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
补充说明
- 若VBoxContainer嵌套在ScrollContainer中,计算位置时需结合
ScrollContainer.scroll_offset修正坐标,避免滚动偏移导致指示器位置错误。 - 可自定义指示器样式,比如换成Line控件、带边框的高亮区域,或修改颜色、尺寸适配你的UI风格。
- 确保容器的
mouse_filter未设置为MOUSE_FILTER_IGNORE,否则无法接收拖放输入事件。
内容的提问来源于stack exchange,提问作者ionarn
相关产品推荐
相关产品推荐

