Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | lxknvlk |
I am adding new elements to ScrollContainer from script. Like a chat. How to make the scroll container auto scroll down to the newest message?
Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | lxknvlk |
I am adding new elements to ScrollContainer from script. Like a chat. How to make the scroll container auto scroll down to the newest message?
Reply From: | jgodfrey |
Here’s an example that adds 100 buttons to a ScrollContainer
, and scrolls the container to the bottom after each button is added. Also, just to better see the effect, it waits 0.1 seconds between adding each button…
extends CanvasLayer
onready var container = $ScrollContainer
onready var vbox = $ScrollContainer/VBoxContainer
onready var scrollbar = $ScrollContainer.get_v_scrollbar()
func _ready():
for i in range(100):
var btn = Button.new()
btn.text = "Button" + str(i)
addItem(btn)
yield(get_tree().create_timer(.1), "timeout")
func addItem(btn):
vbox.add_child(btn)
yield(get_tree(), "idle_frame")
container.scroll_vertical = scrollbar.max_value
Hello people,
I used your answer as a base for a smoothed scrolling version, thanks @Jgodfrey:
extends ScrollContainer
#Call from a parent node the function Scroll_To_Bottom(), it will cycle infinitely.
signal Scroll_Reached_End
signal Scroll_Reached_Top
var TIMER = Timer.new()
var SCROLL = 0
export (float) var DELAY = 2.0 #in seconds
export (int) var SPEED = 1
func _ready():
connect("Scroll_Reached_End",self,"Scroll_Restart")
connect("Scroll_Reached_Top",self,"Scroll_To_Bottom")
TIMER.autostart = 0
TIMER.one_shot = 1
TIMER.wait_time = DELAY
add_child(TIMER)
func _process(delta):
#Will only work if timer isn't active or simply the time_left == 0.
if !TIMER.time_left:
#SCROLL DOWN
if SCROLL == 1:
if (scroll_vertical + get_v_scrollbar().page) < get_v_scrollbar().max_value:
scroll_vertical += SPEED
else:
SCROLL = 0
emit_signal("Scroll_Reached_End")
#SCROLL UP
elif SCROLL == -1:
if scroll_vertical != 0:
scroll_vertical -= SPEED
else:
SCROLL = 0
emit_signal("Scroll_Reached_Top")
func Scroll_Back_Up():
TIMER.start(DELAY)
SCROLL = -1
func Scroll_Restart():
TIMER.start(DELAY*1.5) #Here delay is longer.
SCROLL = -1 #Loop back up.
func Scroll_To_Bottom():
scroll_vertical = 0 #Reset to top first.
TIMER.start(DELAY)
SCROLL = 1
The_Black_Chess_King | 2020-10-20 02:42
Reply From: | ulty |
Maybe an easier way to do it is to use v_scrollbar signal “changed”:
func _ready():
v_scroll = scroll_c.get_v_scrollbar()
v_scroll.connect("changed", self, "scroll_now")
func resize_item_in_scroll_container_or_add_a_child_to_it():
...
lock_out = false # prevent recursion
func scroll_now():
if lock_out == true: # prevent recursion
return
lock_out = true
scroll_c.scroll_vertical = backdrop.rect_min_size.y - scroll_c.rect_size.y
This is good, but it’d be better if we didn’t need a flag.
blurrred | 2021-08-14 04:20