如何在 Godot 中创建可扩展的多行按钮?

发布于 2025-01-11 09:18:10 字数 455 浏览 4 评论 0原文

Godot 中的 Button 只能容纳一行文本。我可以通过将 RichTextLabel 节点放置在按钮内来克服此限制。

现在按钮可以包含更多行文本,但当需要更多行时,其高度不会自动更改。相反,文本只是溢出:

button 的屏幕截图

当然,我可以手动将按钮的大小调整得更大,但我希望根据内部文本的数量自动发生这种情况。具体来说,我以编程方式生成这些按钮的列表,并在 HBoxContainer 内显示,其中一些按钮具有较长的文本,而另一些按钮则具有较短的文本。

有没有办法用 Godot 布局工具来实现这一点?

A Button in Godot can only hold a single line of text. I can overcome this limitation by placing RichTextLabel node inside the button.

Now the button can contain more lines of text, but its height doesn't change automatically when more lines are needed. Instead the text just overflows:

screenshot of button

Of course I can manually resize the button to be higher, but I'd like this to happen automatically depending on the amount of text inside. Specifically, I'm generating a list of these buttons programmatically and showing inside a HBoxContainer, with some buttons having longer and other shorter text.

Is there a way to achieve this with Godot layout tools?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝色星空 2025-01-18 09:18:11

(Godot 3.x)

在不使用脚本的情况下,也可以通过将两个节点作为同级节点包装在容器(例如 MarginContainer)内来实现相同的目标。启用 RichTextLabel 的 fit_content_height 属性,这将导致标签根据需要扩展容器区域,进而调整 Button 的大小。

(Godot 3.x)

Without using scripting, it is also possible to achieve the same goal by wrapping both nodes as sibilings within a container, for example a MarginContainer. Enable the RichTextLabel's fit_content_height property, which will result in the label expanding the container's area as much as necessary, which will in turn resize the Button.

虐人心 2025-01-18 09:18:11

(Godot 4.1.1)我今天尝试实现相同的功能,您可以通过使用节点来实现:

  1. 创建一个PanelContainer并添加一个按钮节点及其内部的标签。您可以调整它们的大小,直到您满意为止。

  2. 将标签的自动换行模式设置为“Word(智能)”。

  3. PanelContainer 的大小调整为您想要的尺寸。

现在您会注意到,当您调整 PanelContainer 大小时,按钮和标签都会动态调整其大小以适合 PanelContainer。我希望这对任何阅读的人都有帮助。

(Godot 4.1.1)I try to realize the same function today,you can achieve this by using nodes:

  1. Create a PanelContainer and add a button node along with a label inside it. You can adjust their sizes until you are satisfied.

  2. Set the label's AutoWrap Mode to "Word (Smart)".

  3. Adjust the size of the PanelContainer to your desired dimensions.

Now you will notice that when you resize the PanelContainer, both the button and the label will dynamically adjust their sizes to fit within the PanelContainer. I hope this is helpful for anyone reading.

知足的幸福 2025-01-18 09:18:11

Godot 4.3 现在为“文本行为”下​​的按钮提供了自动换行模式

Godot 4.3 now has auto-wrap mode for buttons under "Text Behavior"

风苍溪 2025-01-18 09:18:10

由于 Button 位于 Container 中,因此它可以控制其 rect_size。我们能做的最好的事情就是指定一个 rect_min_size。没有预设布局让 Control 依赖于子 Control。因此,要回答发布的问题:不,我们无法使用 Godot 布局工具实现此目的。我们需要一些脚本。


我们需要根据 RichTextLabel 设置 Buttonrect_min_size。我们可以使用 get_content_height 询问其内容的高度。这也意味着我们需要预先设置宽度。但是,当我们设置文本时,它不会立即更新(我们将使用 yield)。


显然您不希望 Container 控制 Button 的高度。如果是这种情况,我认为您可以从 size_flags_vertical 中删除所有标志。

关于宽度,因为正如我之前解释的那样,我们需要设置宽度来获取高度......我建议您让 Container 扩展 Button 的宽度可能的。这意味着在 size_flags_horizo​​ntal 上设置填充和展开标志。

然后,将 RichTextLabel 正确设置为尽可能多地占据父 Button 的宽度,您可以读取它的高度,并使用它来设置 Button 的高度按钮的>rect_min_size。


还有一件事:您需要将 RichTextLabel 的鼠标过滤器设置为“忽略”或“通过”,否则它将阻止按下 Button


这是我想出的代码:

var b := Button.new()
b.size_flags_vertical = 0
b.size_flags_horizontal = SIZE_EXPAND_FILL
add_child(b)

var l := RichTextLabel.new()
l.mouse_filter = Control.MOUSE_FILTER_IGNORE
l.set_anchors_and_margins_preset(Control.PRESET_WIDE)
l.text = "Some\nMultiline\nText"
b.add_child(l)

yield(get_tree(), "idle_frame")
b.rect_min_size.y = l.get_content_height()

我希望根据里面的文本量自动发生

遗憾的是更改文本不会调整大小,也不会更改 RichTextLabel 的最小大小。并且 RichTextLabel 没有“文本已更改”信号。也没有“bbcode 文本已更改”信号。此外,拦截这些属性可能不可行(请参阅 append_bbcode 等)。 使用常规标签可能更容易。

无论如何,我建议制作一个包装 RichTextLabelControl code>,提供您实际需要的任何界面,并且在更改文本的任何方法中,之后您可以执行与此等效的操作:

yield(get_tree(), "idle_frame")
b.rect_min_size.y = l.get_content_height()

Since the Button is in a Container, it is in control of its rect_size. The best we can do is specify a rect_min_size. There is no layout preset to have a Control depend on children Control. So, to answer the question as posted: No, we cannot achieve this with Godot layout tools. We need some scripting.


We need to set the rect_min_size for the Button depending on the RichTextLabel. We can ask it for the height of its content with get_content_height. Which also means we need to set the width beforehand. However, it will not update right away when we set the text (we are going to use yield).


Apparently you don't want the Container to control the height of the Button. If that is the case, I think you can remove all the flags from size_flags_vertical.

About the width, since as I was explaining before we need to set the width to get the height… I suggest you let the Container expand the width of the Button as much a posible. Which mean setting both the Fill and Expand flags on size_flags_horizontal.

Then, with the RichTextLabel properly set to take as much width of the parent Button as possible, you can read it height, and use it to set the height of the rect_min_size of the Button.


One more thing: you want to set the mouse filter of the RichTextLabel to Ignore or Pass, or it will prevent pressing the Button.


This is the code I came up with:

var b := Button.new()
b.size_flags_vertical = 0
b.size_flags_horizontal = SIZE_EXPAND_FILL
add_child(b)

var l := RichTextLabel.new()
l.mouse_filter = Control.MOUSE_FILTER_IGNORE
l.set_anchors_and_margins_preset(Control.PRESET_WIDE)
l.text = "Some\nMultiline\nText"
b.add_child(l)

yield(get_tree(), "idle_frame")
b.rect_min_size.y = l.get_content_height()

I'd like this to happen automatically depending on the amount of text inside

Sadly changing the text does not resize, nor change the minimum size of the RichTextLabel. And RichTextLabel does not have a "text changed" signal. Nor "bbcode text changed" signal. Furthermore, it might not be feasible to intercept these properties (see append_bbcode et.al). It is proabaly easier to do with a regular Label.

Anyway, what I'm going to suggest for this is to make a Control that wraps the RichTextLabel, offers whatever interface you actually need, and in any method where you change the text, afterwards, you do the equivalent of this:

yield(get_tree(), "idle_frame")
b.rect_min_size.y = l.get_content_height()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文