How to change ScrollbarContainer's Scrollbar Position?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By wombatTurkey
:warning: Old Version Published before Godot 3 was released.

I’m reading here:

And it says we can change the value of the scroll container

void set_v_scroll ( int val ) Set vertical scroll value.

So, my code is like so:

var ChatRoomMessages = get_node("ChatRoom/ScrollContainer/VBoxContainer")
var ChatRoomContainer = get_node("ChatRoom/ScrollContainer")
for x in range(1, 55):
	var new = Label.new()
	#new.set_opacity(0.5)
	tween.interpolate_method(new, "set_opacity", 0, 1, 0.5 * x, tween.TRANS_LINEAR, tween.EASE_OUT)
	tween.start()
	new.set_text('hello dude')
	ChatRoomMessages.add_child(new)
	ChatRoomContainer.set_enable_v_scroll(true)
	ChatRoomContainer.set_v_scroll(55)
	print(ChatRoomContainer.is_v_scroll_enabled())

new is just referencing to Label.new().

Everything works. The label gets appened to my ChatRoom Container which looks like this:

My problem is, I’m setting the set_v_scroll value to 55, or any value and my scrollbar position is not changing. I even printed out to check if the is_v_scroll_enabled method returns True, and it does… Any idea?

I guess it does not scroll because VBoxContainer size is smaller than ScrollContainer.
Try it again with more Labels to make VBoxContainer size is bigger than ScrollContainer.

volzhs | 2016-05-17 02:16

Hey Volzhs it does scroll though (the scrollbar shows up and works fine) – its just the scrollbar’s position doesn’t change when I call set_v_scroll :frowning:

wombatTurkey | 2016-05-17 02:48

how about calling yield(get_tree(), "idle_frame") just before call set_v_scroll

volzhs | 2016-05-17 13:20

Wow, okay so yield(get_tree(), "idle_frame") does work. Can you explain to me how exactly this does work? So I don’t make the mistake again, lol. I would of never knew :stuck_out_tongue:

If you make an answer I’ll accept it.

wombatTurkey | 2016-05-17 19:58

I know you have a solution but it seems a bit hacky (er, with respect to the answerer who obviously knows much more about Godot than me :). Why do you need to do the last 3 lines 55 times in the loop? Just un-indent them and see if that works.

duke_meister | 2016-05-17 23:17

@duke, yeah it was getting called in the for loop too I forgot to unindent after. But, that doesn’t matter I think, it still happens even if it wasn’t in the loop. Seems like yield is the fix, haha. I would of never known :stuck_out_tongue:

wombatTurkey | 2016-05-18 04:10

:bust_in_silhouette: Reply From: volzhs

Calling yield(get_tree(), "idle_frame") before set_v_scroll will make it works.

I guess, the size of scroll container will be calculated when frame ends if adding gui control to scroll container, because of performance issue.
Performance will be drop if calculates every time when adding a gui control in same frame.

In my case your solution failed to work in some cases (I was implementing a simple chat with networking functions and it was failing when receiving a message).


So, another way of resolving the problem is to wait for a scrollbar change.
As stated on the documentation, you can observe changes made to the scrollbar (max_value in this case) to scroll to the end.

In my case, the code needed after adding the instance of a message was the following :

# Get variables
var scrollContainer: ScrollContainer = $path/to/ScrollContainer;
var bar: VScrollBar = scrollContainer.get_v_scrollbar();

# Wait for scrollbar update
yield(bar, "changed")

# Scroll to the bottom once the scrollbar has been updated
scrollContainer.scroll_vertical = bar.max_value;

Hope it helps!

zetarov | 2020-03-10 22:58

:bust_in_silhouette: Reply From: RadianDRZ

A combination of wombatTurkey and zetarov works:
Note: replace $“.” with your path to ScrollContainer (and also not VBoxContainer)

yield(get_tree(), "idle_frame")
$".".set_v_scroll(55)