Updating Real Time

Started by RamblingBaba, 01 May 2020, 03:30:21

RamblingBaba

Hello, I'm having trouble figuring out how to update the text live. I have 3 sliders, 3 labels sayings "Red, Green, Blue", and 3 labels that are supposed to show the value of each individual slider. The sliders change the color of the background of a child window. I've basically stripped out the "All Widgets Example" provided.

1st Question: How can I change the position of the slider at startup? It always starts at 0 (it's at zero now as I tried to fix), yet I assumed setValue would position it to the value correctly.
(UPDATE: I saw this on a thread " I've added a ThumbWithinTrack option to the renderer in TGUI 0.9-dev. Setting it to true will make the side of the thumb align with the side of the track when the thumb has minimum or maximum value."

2nd Question:   (SOLVED, I FIGURED IT OUT, HAD TO GET FROM GUI. I STILL HAVE TO CLICK EACH SLIDER FOR IT TO UPDATE THE VALUES FOR THE CHILD BACKGROUND)
Code (cpp) Select
   
int r = 0, g = 0, b = 0;
...
        // Red
        auto slider = tgui::Slider::create();
        slider->setRenderer(theme.getRenderer("Slider"));
        slider->setPosition(55, 360);
        slider->setSize(200, 18);
        slider->setValue(0);
        slider->setMaximum(255);
        slider->setMinimum(0);
        slider->connect("ValueChanged", [&]() {
            r = slider->getValue();

            child->getRenderer()->setBackgroundColor({ (sf::Uint8)r, (sf::Uint8)g, (sf::Uint8)b });
            gui.get<tgui::Label>("red_value")->setText(std::to_string((int)gui.get<tgui::Slider>("red").get()->getValue()));
        });
        gui.add(slider, "red");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText("Red");
        label->setPosition("red.left - width - 10","red.top");
        label->setTextSize(14);
        gui.add(label, "red_label");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText(std::to_string(r));
        label->setPosition("red.left + red.width + 10", "red.top");
        label->setTextSize(14);
        gui.add(label, "red_value");

        // Green
        slider = tgui::Slider::copy(slider);
        slider->setPosition("red.left", "red.top + 35");
        slider->connect("ValueChanged", [&]() {
            g = slider->getValue();

            child->getRenderer()->setBackgroundColor({ (sf::Uint8)r, (sf::Uint8)g, (sf::Uint8)b });
            gui.get<tgui::Label>("green_value")->setText(std::to_string((int)gui.get<tgui::Slider>("green").get()->getValue()));

            });
        gui.add(slider, "green");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText(std::to_string(g));

        label->setPosition("green.left + green.width + 10", "green.top");
        label->setTextSize(14);
        gui.add(label, "green_value");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText("Green");
        label->setPosition("green.left - width - 10", "green.top");
        label->setTextSize(14);
        gui.add(label, "green_label");

        // Blue
        slider = tgui::Slider::copy(slider);
        slider->setPosition("green.left", "green.top + 35");
        slider->connect("ValueChanged", [&]() {
            b = slider->getValue();
            child->getRenderer()->setBackgroundColor({ (sf::Uint8)r, (sf::Uint8)g, (sf::Uint8)b });
            gui.get<tgui::Label>("blue_value")->setText(std::to_string((int)gui.get<tgui::Slider>("blue").get()->getValue()));

            });
        gui.add(slider, "blue");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText("Blue");
        label->setPosition("blue.left - width - 10", "blue.top");
        label->setTextSize(14);
        gui.add(label, "blue_label");

        label = tgui::Label::create();
        label->setRenderer(theme.getRenderer("Label"));
        label->setText(std::to_string(b));
        label->setPosition("blue.left + blue.width + 10", "blue.top");
        label->setTextSize(14);
        gui.add(label, "blue_value");


Here is the code for what I'm doing with the sliders and labels. How can I get these label values to change as I scroll? EDIT: I got it to scroll and display the value correctly, but I realized the color of the background is definitely not accurate.

3rd: What does the method update actually do? (Besides the obvious) What is being updated and when would I want to manually call update? Also, what is updateTime() method in the Gui suppose to do?

4th: How do I manually call a Widgets connect callback?

Any help would greatly be appreciated, thanks!

texus

#1
Quote1st Question: How can I change the position of the slider at startup? It always starts at 0 (it's at zero now as I tried to fix), yet I assumed setValue would position it to the value correctly.
Calling setSlider->setValue(x) after creating the slider does change the value and will set the thumb on a different position. If not then you are probably calling setValue(0) somewhere afterwards.

Quote2nd Question:   (SOLVED, I FIGURED IT OUT, HAD TO GET FROM GUI. I STILL HAVE TO CLICK EACH SLIDER FOR IT TO UPDATE THE VALUES FOR THE CHILD BACKGROUND)
The "ValueChanged" callback is only going to be called when you actually change the value, either by clicking on it or by calling setValue(). So if you don't give your window the right background color initially then it of course won't be set until the first time you change the slider.

Quote3rd: What does the method update actually do? (Besides the obvious) What is being updated and when would I want to manually call update? Also, what is updateTime() method in the Gui suppose to do?
The update function is an internal function which should never be called manually. It is used to inform widgets that time has passed. Only a few widgets do something with this information, e.g. edit box will blink its caret. The updateTime function in Gui (also meant for internal use and called from inside Gui::draw()), is the function that will call the update() function on all widgets in the gui.
I guess I should rename update() to updateTime() as well to make it more clear what is being updated.

Quote4th: How do I manually call a Widgets connect callback?
You aren't meant to do this. If you really must, you could use slider->onValueChange.emit(slider.get(), slider->getValue());

Edit:
Quotebut I realized the color of the background is definitely not accurate.
You are using "[&]" as lambda capture. Is the "slider" object still alive when the lambda is executed (when the value is changed)? It not then you are causing undefined behavior. Widgets in TGUI are stored as pointers, so you can copy them inside the lambda by value:
Code (cpp) Select
slider->connect("ValueChanged", [&,slider]() { ... });

RamblingBaba

#2
[SOLVED] I just retrieved from the gui and it worked correctly.  Thank you.




Here is the code, I posted it all for clarity. So the "red" slider starts off just a tad past zero. But the others start at zero. I checked for calls of setValue and it's only called on the sliders. I have 3 comments // Red, // Green, // Blue for where I initialize the Sliders. Thanks

Code (cpp) Select
tgui::Theme theme{ "themes/Black.txt" };

gui.add(tgui::Picture::create("RedBackground.jpg"));

auto r = 0.f, g = 0.f, b = 0.f;
auto r2 = 0.f, g2 = 0.f, b2 = 0.f;


auto menu = tgui::MenuBar::create();
menu->setRenderer(theme.getRenderer("MenuBar"));
menu->setSize(static_cast<float>(window.getSize().x), 22.f);
menu->addMenu("File");
menu->addMenuItem("Load");
menu->addMenuItem("Save");
menu->addMenuItem("Exit");
menu->addMenu("Edit");
menu->addMenuItem("Copy");
menu->addMenuItem("Paste");
menu->addMenu("Help");
menu->addMenuItem("About");
menu->connectMenuItem("File", "Exit", [&]() {window.close(); });
gui.add(menu, "menu");

auto child = tgui::ChildWindow::create();
child->setRenderer(theme.getRenderer("ChildWindow"));
child->setSize(250, 120);
child->setPosition(420, 80);
child->setTitle("Child window");
gui.add(child, "child");

auto label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText("Hi! I'm a child window.");
label->setPosition(30, 30);
label->setTextSize(15);
child->add(label, "child_label");

auto editBox = tgui::EditBox::create();
editBox->setRenderer(theme.getRenderer("EditBox"));
editBox->setSize(200, 25);
editBox->setTextSize(18);
editBox->setPosition(10, 270);
editBox->setDefaultText("Click to edit text...");

editBox->onReturnKeyPress( [&]() {
gui.get("child")->setVisible(true);
auto lbl = gui.get<tgui::ChildWindow>("child")->get<tgui::Label>("child_label");
lbl->setText(gui.get<tgui::EditBox>("editbox")->getText());
});
gui.add(editBox, "editbox");

auto button = tgui::Button::create();
button->setRenderer(theme.getRenderer("Button"));
button->setPosition("editbox.left + editbox.width + 5", "editbox.top");
button->setText("Show Popup");
button->setSize(100, 30);
button->onPress( [&]() {
gui.get<tgui::ChildWindow>("child")->setVisible(
!gui.get<tgui::ChildWindow>("child")->isVisible());
if (gui.get<tgui::ChildWindow>("child")->isVisible())
gui.get<tgui::Button>("toggleChildButton")->setText("Hide Child");
else
gui.get<tgui::Button>("toggleChildButton")->setText("Show Child");

});
gui.add(button, "toggleChildButton");


[b]// Red
auto slider = tgui::Slider::create();
slider->setRenderer(theme.getRenderer("Slider"));
slider->setPosition(55, 360);
slider->setSize(200, 18);
slider->setValue(150);
slider->setMaximum(255);
slider->setMinimum(0);
slider->setStep(1);
slider->getRenderer()->setThumbWithinTrack(true);
slider->onValueChange( [&]() {[/b]
const auto checkBG = gui.get<tgui::RadioButton>("rBGColor");
const auto checkTC = gui.get<tgui::RadioButton>("rTextColor");
if (checkBG->isChecked())
{
r = gui.get<tgui::Slider>("red")->getValue();
child->getRenderer()->setBackgroundColor({ static_cast<sf::Uint8>(r), static_cast<sf::Uint8>(g), static_cast<sf::Uint8>(b) });
gui.get<tgui::Label>("red_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("red").get()->getValue())));
}
else if (checkTC->isChecked()) {
r2 = gui.get<tgui::Slider>("red")->getValue();
auto lb = gui.get<tgui::ChildWindow>("child")->get<tgui::Label>("child_label");
lb->getRenderer()->setTextColor({ static_cast<sf::Uint8>(r2), static_cast<sf::Uint8>(g2), static_cast<sf::Uint8>(b2) });
gui.get<tgui::Label>("red_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("red").get()->getValue())));
}
});
gui.add(slider, "red");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText("Red");
label->setPosition("red.left - width - 10", "red.top");
label->setTextSize(14);
gui.add(label, "red_label");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText(std::to_string(r));
label->setPosition("red.left + red.width + 10", "red.top");
label->setTextSize(14);
gui.add(label, "red_value");

[b]// Green
slider = tgui::Slider::create();
slider->setRenderer(theme.getRenderer("Slider"));
slider->setPosition("red.left", "red.top + 35");
slider->setSize(200, 18);
slider->setValue(150);
slider->setMaximum(255);
slider->setMinimum(0);
slider->setStep(1);
slider->onValueChange([&]() {[/b]
auto checkBG = gui.get<tgui::RadioButton>("rBGColor");
auto checkTC = gui.get<tgui::RadioButton>("rTextColor");
if (checkBG->isChecked())
{
g = gui.get<tgui::Slider>("green")->getValue();
child->getRenderer()->setBackgroundColor({ static_cast<sf::Uint8>(r), static_cast<sf::Uint8>(g), static_cast<sf::Uint8>(b) });
gui.get<tgui::Label>("green_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("green").get()->getValue())));
}
else if (checkTC->isChecked()) {
g2 = gui.get<tgui::Slider>("green")->getValue();
auto lb = gui.get<tgui::ChildWindow>("child")->get<tgui::Label>("child_label");
lb->getRenderer()->setTextColor({ static_cast<sf::Uint8>(r2), static_cast<sf::Uint8>(g2), static_cast<sf::Uint8>(b2) });
gui.get<tgui::Label>("green_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("green").get()->getValue())));
}
});
gui.add(slider, "green");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText(std::to_string(g));
label->setPosition("green.left + green.width + 10", "green.top");
label->setTextSize(14);
gui.add(label, "green_value");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText("Green");
label->setPosition("green.left - width - 10", "green.top");
label->setTextSize(14);
gui.add(label, "green_label");

[b]// Blue
slider = tgui::Slider::create();
slider->setRenderer(theme.getRenderer("Slider"));
slider->setPosition("green.left", "green.top + 35");
slider->setSize(200, 18);
slider->setValue(150);
slider->setMaximum(255);
slider->setMinimum(0);
slider->setStep(1);

slider->onValueChange([&]() {[/b]
auto checkBG = gui.get<tgui::RadioButton>("rBGColor");
auto checkTC = gui.get<tgui::RadioButton>("rTextColor");
if (checkBG->isChecked())
{
b = gui.get<tgui::Slider>("blue")->getValue();
child->getRenderer()->setBackgroundColor({ static_cast<sf::Uint8>(r), static_cast<sf::Uint8>(g), static_cast<sf::Uint8>(b) });
gui.get<tgui::Label>("blue_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("blue").get()->getValue())));
}
else if (checkTC->isChecked()) {
b2 = gui.get<tgui::Slider>("blue")->getValue();
auto lb = gui.get<tgui::ChildWindow>("child")->get<tgui::Label>("child_label");
lb->getRenderer()->setTextColor({ static_cast<sf::Uint8>(r2), static_cast<sf::Uint8>(g2), static_cast<sf::Uint8>(b2) });
gui.get<tgui::Label>("blue_value")->setText(std::to_string(static_cast<int>(gui.get<tgui::Slider>("blue").get()->getValue())));
}
});

gui.add(slider, "blue");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText("Blue");
label->setPosition("blue.left - width - 10", "blue.top");
label->setTextSize(14);
gui.add(label, "blue_label");

label = tgui::Label::create();
label->setRenderer(theme.getRenderer("Label"));
label->setText(std::to_string(b));
label->setPosition("blue.left + blue.width + 10", "blue.top");
label->setTextSize(14);
gui.add(label, "blue_value");

auto radioButton = tgui::RadioButton::create();
radioButton->setRenderer(theme.getRenderer("RadioButton"));
radioButton->setPosition(20, 140);
radioButton->setText("Background Color");
radioButton->setSize(25, 25);

gui.add(radioButton, "rBGColor");

radioButton = tgui::RadioButton::create();
radioButton->setRenderer(theme.getRenderer("RadioButton"));
radioButton->setPosition(20, "rBGColor.top - 27");
radioButton->setText("Text Color");
radioButton->setSize(25, 25);
gui.add(radioButton, "rTextColor");


The reason I wanted to call a function manually is that when I change the radio button to "background" or "text color" the color doesn't update unless I click each individual slider again. Which was why I was curious of what update does. I guess I was just being lazy and didn't want to call the same color change inside the radio.onCheck() again. But it works when I do that, I was just hoping I could call the functions of the sliders to accomplish for me. Thanks