The idea of using a custom widget is to avoid calling setPosition. Apparently the function call has too much overheat so the widgets have to be moved without the function being called for every pixel the scrollbar moves. To do this, we will translate the widgets when drawing. You will call setPosition once to place them in the panel, but when the scrollbar moves you will not call setPosition again and instead dynamically change where the widget is drawn.
Instead of using tgui::Panel, you use your own CustomPanel class that inherits from tgui::Panel. This class needs access to the scrollbar somehow (e.g. it has a pointer to the scrollbar as a member variable). You have to override the draw function (adding draw as a member function of your class) like this:
void CustomPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform.translate({0, -(float)scrollbar->getValue()});
Panel::draw(target, states);
}
That will move all widgets up with scrollbar->getValue() pixels when drawing.
When handling events, the panel must also know about the fact that the widgets aren't located where they claim to be, so mouseOnWidget has to be implemented like this in your class:
bool CustomPanel::mouseOnWidget(float x, float y) const {
Panel::mouseOnWidget(x, y + scrollbar->getValue());
}
The same has to be done for leftMousePressed and leftMouseReleased.
Note: this code is based in 0.7, to do the same in 0.8-dev just have a look at how the parameters of the functions are in the tgui::Panel class.
Edit: can you check one more thing? Does the lag also occur when you have a ListBox with some items in it (which is very similar situation to having a scrollable panel of labels)?