Godot的RichTextLabel富文本标签,鼠标拖拽滚动,方向键滚动,底部吸附,自动滚动

零、godot介绍

Godot 是一款游戏引擎软件,可以用来写游戏

中文界面,中文文档,MIT开源,免费使用全部功能,无分成,跨平台,轻量,不会下架(因为没上架)

官网链接:https://godotengine.org/zh-cn/

文档链接:https://docs.godotengine.org/zh-cn/

一、下载godot

二、软件安装

在电脑硬盘空间里找个地方创建GodotSoftware文件夹用来放置godot本体,例如参考以下目录结构

bash 复制代码
Godot/
├── _rcedit/
│   └── rcedit-x64.exe
├── _导出模板/
│   └── Godot_v4.4.1-stable_export_templates.tpz
├── _导出位置/
│   ├── Windows/
│   └── Android/
├── _静态Web服务器软件/
│   └── ran_windows_amd64.exe
├── _素材/
│   ├── images/
│   ├── audio/
│   ├── shader/
│   └── fonts/
├── _文档/
│   └── XX文档.pdf
├── GodotSoftware/
│   └── Godot_v4.4.1-stable_win64.exe
└── GodotProjects/
    ├── Project_Game1/
    │   ├── .godot/
    │   ├── scenes/
    │   ├── scripts/
    │   └── res/
    └── Project_Game2/
        ├── .godot/
        ├── scenes/
        ├── scripts/
        └── res/

三、创建项目

  • 1 运行Godot_v4.4.1-stable_win64.exe

  • 2 点击创建或者新建项目

  • 3 项目名称

    输入框项目名称:可拖拽的富文本标签

  • 4 设置项目路径

    (GodotProjects文件夹要点进去,如果不点进去godot的最近使用就会记录成父文件夹)

  • 5 设置版本控制

    选择

  • 6 创建完成

    点击创建按钮,创建完成

四、创建RichTextLabel

  • 1 创建:

    使用场景面板,点击其他节点,输入rich找到并选中RichTextLabel,点击创建按钮

  • 2 保存
    *符号表示这个场景没有保存

    点击场景 - 保存场景,在弹出场景另存为...窗口中直接点击保存按钮即可

  • 3 确认保存

    左下角文件系统多了一个rich_text_label.tscn,这就是已保存的场景文件

五、切换编辑器界面

在godot窗口正上方,有五个选项,分别是 2D 3D 脚本代码 游戏结果预览 资源库

点击并切换到2D,这样才能查看创建的RichTextLabel长什么样子

六、缩放2D预览窗口

在"红框圈住的区域"滚动鼠标滚轮直到绿框内的数值比较低,比如(18.0%)

粉色#cb3950横线,绿色#78b315竖线,紫色#565694方框,这些线组成的方框就是最终玩家看到的区域

七、设置RichTextLabel的锚点预设

  • 1 在左侧场景树中点击选中RichTextLabel后,在2D预览界面会看到一堆控制手柄
  • 2 设置锚点(这个按钮在视图按钮附近)

点击锚点预设设置按钮将 RichTextLabel 的锚点设置为整个矩形

按快捷键Ctrl+S保存

  • 3 效果截图:

八、设置 RichTextLabel 中的文本内容

  • 1 勾选启用BBCode

  • 2 点击展开按钮显示一个更大的输入框更容易编辑
    (注意:如果整个Godot窗口怎么点都没反应,说明你把这个输入框弹窗最小化到左下角了)

    输入以下内容

    [b]加粗[/b][i]斜体[/i][u]下划线文本[/u][s]删除线文本[/s][color=aqua]青色文本[/color][color=maroon]深红色文本[/color][color=teal]蓝绿色文本[/color]
    [color=6cf]自定义颜色(十六进制)[/color][color=6cf8]半透明颜色(带alpha通道的十六进制)[/color]
    [code][color=e3e3e3][color=bf67ff]function[/color] [color=7cacf8]show_alert/color { alert([color=fe8d59]"代码字体"[/color]); }[/color][/code]
    [url=https://godotengine.org/zh-cn/]Godot官网[/url] [url={"action": "open_url", "url": "https://godotengine.org/zh-cn/"}] JSON式链接[/url]url需要配合 meta_clicked 信号点击才有用
    [font_size=24]大号字体文本[/font_size]
    [left]左对齐文本[/left]
    [center]居中对齐文本[/center]
    [right]右对齐文本[/right]

    [wave amp=30 freq=1][b][color=ff0000]波浪效果文本,上下波动显示。[/color][/b][/wave]
    [tornado radius=20 freq=1][i][color=0000ff]旋风效果文本,在圆圈内旋转显示。[/color][/i][/tornado]
    [shake rate=3 level=15][u][color=008000]抖动效果文本,摇晃显示。[/color][/u][/shake]
    [rainbow freq=0.5 sat=15 val=20][b]彩虹效果文本,随时间变化颜色。[/b][/rainbow]
    [fade start=2 length=10][i][color=800080]渐隐效果文本,部分字符逐渐消失。[/color][/i][/fade]
    [pulse color=#00FFAA height=5.0 freq=1.5][b]这是脉冲效果文本,文字上下脉动并改变颜色。[/b][/pulse]

    [img]res://icon.svg[/img][img color=333]res://icon.svg[/img][img=100]res://icon.svg[/img][img tooltip="嘿嘿嘿"]res://icon.svg[/img]
    [img=100x1000]res://icon.svg[/img]

按快捷键Ctrl+S保存

  • 3 最终效果:

九、设置项目窗口大小(窗口太大截图就大,文章里的图就会缩小变糊)

点击项目-项目设置

在项目设置中,将显示 - 窗口 - 视口宽度设置为700,将显示 - 窗口 - 视口高度设置为400

(一般情况下,高级设置是要打开的,但是这次无所谓)

十、运行当前场景

(运行场景时,场景和脚本会自动保存)

右上角,按F6或者按按钮运行当前场景

运行结果:

关闭展示的DEBUG窗口

十一、添加脚本

  • 1 添加脚本
    1.1 右键RichTextLabel,点击添加脚本选项

    1.2 或者选中RichTextLabel,直接点击添加脚本图标
  • 2 创建脚本
    在"设置节点的脚本"窗口中直接点击创建即可
  • 3 效果截图
    文件系统新出现了一个rich_text_label.gd脚本文件
  • 4 折叠输出面板
    在窗口底部,将输出点成白色(按快捷键Alt+O)
  • 5 折叠脚本文件名面板
    在窗口底部,点击左箭头开关脚本面板(快捷键Ctrl+)
  • 6 按快捷键Ctrl+S保存

十二、编写脚本(RichTextLabel的链接点击功能)

  • 1 连接信号
    选中RichTextLabel,右侧属性面板找到节点 - 信号
    点击连接...按钮(或者双击meta_clicked(meta: Variant))

    在"连接信号到方法"窗口直接点击连接按钮即可
  • 2 连接效果:
    红框处的图标表明:这个方法和信号连接了,不能随便删除(可以信号断开之后再删除)
  • 3 修改res://rich_text_label.gd
python 复制代码
extends RichTextLabel

func _ready() -> void:
	add_godot_doc_link()
	pass

func _on_meta_clicked(meta: Variant) -> void:
	# BBCode 不支持字典类型,会以字符串形式存储,需要手动解析。
	# 想要字典类型可以使用 push_meta 方法
	if meta is Dictionary:
		print("meta is Dictionary")
		var meta_recv_dict = meta as Dictionary
		if meta_recv_dict.has_all(["action", "url"]) and meta_recv_dict.action == "open_url":
			OS.shell_open(str(meta_recv_dict.url))
		else:
			print("字典中缺键")
	else:
		var json = JSON.new()
		var error = json.parse(meta)
		if error == OK:
			# 解析json
			var meta_recv = json.data
			if typeof(meta_recv) == TYPE_DICTIONARY:
				var meta_recv_dict = json.data as Dictionary
				if meta_recv_dict.has_all(["action", "url"]) and meta_recv_dict.action == "open_url":
					OS.shell_open(str(meta_recv_dict.url))
				else:
					print("字典中缺键")
			else:
				print("不是字典类型")
		else:
			# 直接当作网址字符串
			OS.shell_open(str(meta))

func add_godot_doc_link():
	add_text("\n")
	var doc_url_metadata = { "action": "open_url", "url": "https://docs.godotengine.org/zh-cn/" }
	push_meta(doc_url_metadata, RichTextLabel.META_UNDERLINE_ON_HOVER, "tooltip_random_VbJbHn")
	push_color("#59a1e0")
	add_text("点击访问godot文档")
	pop()
	pop()

按快捷键Ctrl+S保存

  • 4 查看效果:按F6运行当前场景,点击这三个url就会调用系统浏览器访问godot链接

  • 5 关闭展示的DEBUG窗口

  • 6 点击func左侧的折叠按钮折叠方法,折叠_on_meta_clickedadd_godot_doc_link

十三、编写脚本(RichTextLabel的鼠标拖拽滚动功能)

  • 1 写一个转换方法,将布尔值转换为正1或者-1方便后续计算
python 复制代码
# 根据方向标志返回乘数(-1 或 1)
func get_direction_multiplier(value: bool) -> int:
	return -1 if value else 1
  • 2 写一个控制滚动位置的方法
python 复制代码
func set_scroll_value(value: float, block_duration: float = 0.0) -> void:
	# 例:block_time可以使用0.01
	if block_duration > 0:
		# 阻塞这个函数一小段时间, 不然获取到的max_value是旧的
		await get_tree().create_timer(block_duration).timeout
	v_scroll_bar.value = clamp(value, v_scroll_bar.min_value, v_scroll_bar.max_value)
  • 3 鼠标拖拽用到的变量(一般写在_ready方法之前)

    鼠标拖拽

    @export var invert_drag_direction: bool = true
    @onready var v_scroll_bar = get_v_scroll_bar()
    var is_dragging: bool = false
    var drag_start_pos: Vector2 = Vector2.ZERO
    var scroll_value: float = 0.0

  • 4 连接信号
    选中RichTextLabel,连接gui_input(event: InputEvent)信号,方法_on_gui_input(event: InputEvent)

  • 5 写_on_gui_input方法

python 复制代码
func _on_gui_input(event: InputEvent) -> void:
	if event is InputEventMouseButton:
		if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
			# 开始拖拽
			is_dragging = true
			drag_start_pos = event.position
			scroll_value = v_scroll_bar.value
		elif not event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
			# 结束拖拽
			is_dragging = false
	elif event is InputEventMouseMotion and is_dragging:
		# 拖拽中
		var deltay = event.position.y - drag_start_pos.y
		var new_value = scroll_value + deltay * get_direction_multiplier(invert_drag_direction)
		set_scroll_value(new_value)
  • 6 运行
    按F6运行当前场景
    RichTextLabel区域按下鼠标左键不松手,上下移动光标,然后松开鼠标左键
    效果展示(动图已压缩,能看出来鼠标拖拽好使就行):

十四、编写脚本(RichTextLabel的方向键滚动功能)

  • 1 创建方向键滚动用到的变量(一般写在_ready方法之前)
python 复制代码
# 方向键控制
@export var invert_key_direction: bool = false
var key_scroll_step: int = 10
var is_mouse_inside: bool = false
  • 2 复制粘贴这两个方法,下一步再连接信号(用来控制is_mouse_inside的真假)
python 复制代码
func _on_mouse_entered() -> void:
	is_mouse_inside = true

func _on_mouse_exited() -> void:
	is_mouse_inside = false

效果截图(func左侧没有连接图标,因为还没连接):

  • 3 连接信号
    选中RichTextLabel,找到并双击mouse_entered()信号,接收方法名正好是_on_mouse_entered,点击连接
    选中RichTextLabel,找到并双击mouse_exited()信号,接收方法名正好是_on_mouse_exited,点击连接
    已连接效果截图:
  • 4 在_input方法判断按键
python 复制代码
func _input(event: InputEvent) -> void:
	if event is InputEventKey and event.pressed and is_mouse_inside:
		var step = key_scroll_step
		if event.ctrl_pressed:
			step *= 50
		elif event.shift_pressed:
			step *= 10
		elif event.alt_pressed:
			step = 1
		if event.keycode == KEY_UP:
			var new_value = v_scroll_bar.value + (step * -1 * get_direction_multiplier(invert_key_direction))
			set_scroll_value(new_value)
		elif event.keycode == KEY_DOWN:
			var new_value = v_scroll_bar.value + (step * get_direction_multiplier(invert_key_direction))
			set_scroll_value(new_value)

十四、查看效果

  • 1 为了查看效果,新建一个场景并把RichTextLabel当作子场景
    场景 - 新建场景 - 其他节点
  • 2 选择VBoxContainer
  • 3 选中刚创建好的VBoxContainer节点,按F2重命名为Test_rtextP(有测试前缀,是RichTextLabel的父节点)
    右键Test_rtextP实例化子节点

    点击选择rich_text_label.tscn作为实例化的子节点
  • 4 再实例化一个子节点,选择rich_text_label.tscn,让Test_rtextP中包含两个RichTextLabel
    节点结构如图:
  • 5 切换到2D预览显示模式
    选中Test_rtextP,设置锚点预设为整个矩形

    同时选中Test_rtextP的两个子节点,在右侧的检查器中找到Control - layout - Custom Minimum Size
    y设置为180
    (检查器向下滚动大概2/3处)

  • 6 切换到2D预览显示模式查看效果
  • 7 按Ctrl+S将这个场景保存为test_rtext_p.tscn
  • 8 按F6运行当前场景
    随机按上方向键和下方向键,鼠标所在位置的富文本就会滚动
  • 9 关闭DEBUG窗口
    选中Test_rtextP的子节点RichTextLabel,点击在编辑器中打开

    选中RichTextLabel,点击打开脚本

十五、编写脚本(RichTextLabel的底部吸附功能)

  • 1 创建变量
python 复制代码
# 底部吸附滚动条
var random_append_text_timer = Timer.new()
var lock_bottom = true
var lock_bottom_threshold = 100
signal text_updated

Ctrl+S保存,右侧节点 - 信号就会多出来一个text_updated()信号(不保存其实也会显示)

  • 2 创建三个方法
python 复制代码
func add_rand_append_text_timer():
	add_child(random_append_text_timer)
	random_append_text_timer.timeout.connect(_on_random_append_text_Timer_timeout)
	random_append_text_timer.one_shot = true
	random_append_text_timer.start(randf_range(1.0, 2.0))

func _on_random_append_text_Timer_timeout():
	append_text("\n文本" + str(randf()))
	text_updated.emit()
	
	random_append_text_timer.wait_time = randf_range(1.0, 2.0)
	random_append_text_timer.start()

func _on_text_updated() -> void:
	if v_scroll_bar.max_value - v_scroll_bar.value < lock_bottom_threshold + size.y:
		set_scroll_value(v_scroll_bar.max_value, 0.01)
	# 文本量过大直接清空(超宽显示器?)
	if get_line_count() > 1000:
		text = ""
  • 3 连接信号
    在信号界面双击text_updated()信号,连接到_on_text_updated方法上
  • 4 修改_ready方法,把add_rand_append_text_timer填进去
python 复制代码
func _ready() -> void:
	add_godot_doc_link()
	add_rand_append_text_timer()
	pass
  • 5 按F6运行当前场景查看效果
    将文本手动滚动到底部,新加了文本之后就会自动滚动
    如果滚动位置离底部较远,则不会滚动
  • 6 注意:lock_bottom_threshold变量最好和新添加文本的高度有关,新添加文本高度过大,底部吸附就失效了

十六、编写脚本(RichTextLabel的自动滚动功能)

  • 1 创建变量
python 复制代码
# 自动滚动
@export var auto_scroll_speed_normal = 50
var auto_scroll_speed_fast = auto_scroll_speed_normal * 20
var auto_scroll_speed = auto_scroll_speed_normal
  • 2 创建方法(将auto_scroll方法写到_process中)
python 复制代码
func _process(delta: float) -> void:
	auto_scroll(delta)

func auto_scroll(delta) -> void:
	v_scroll_bar.value += auto_scroll_speed * delta
	if Input.is_action_just_pressed("ui_accept"):
		auto_scroll_speed = auto_scroll_speed_fast
	if Input.is_action_just_released("ui_accept"):
		auto_scroll_speed = auto_scroll_speed_normal
  • 3 按F6运行当前场景
    运行之后自动滚动
    如果按住空格,会用另一个更快的速度滚动("ui_accept"是godot内置的按键映射,其中一个触发按键就是空格)

十七、退出

🥳进行一个出的退操作

<>
<>
<>
<>
<>
<>

相关推荐
benben0442 小时前
Unity3D仿星露谷物语开发54之退出菜单及创建可执行文件
游戏·ui·unity·游戏引擎
Magnum Lehar5 小时前
vulkan游戏引擎vulkan部分的fence实现
java·前端·游戏引擎
朗迹 - 张伟5 小时前
Unity数字人开发笔记
笔记·unity·游戏引擎
Luna-player6 小时前
在 Unity 中,Start 方法直接设置 RectTransform 的位置,时出现问题,与预计位置不匹配。
经验分享·unity·游戏引擎
qq_23857086236 小时前
Unity性能优化
unity·游戏引擎
Magnum Lehar19 小时前
vulkan游戏引擎的pipeline管道实现
java·开发语言·游戏引擎
Magnum Lehar19 小时前
vulkan游戏引擎的vulkan/shaders下的image实现
java·前端·游戏引擎
熵减画眉19 小时前
科技趋势分析系统(BBC)技术全解
人工智能·python·科技·机器学习·unity·自然语言处理·游戏引擎
虾球xz21 小时前
游戏引擎学习第314天:将精灵拆分成多个层
linux·c++·学习·游戏引擎
Magnum Lehar21 小时前
vulkan游戏引擎vulkan部分的frame_buffer实现
java·前端·游戏引擎