Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - GetterSetter

#1
Okay, thank you, texus!
#2
Hello, I have a set of textures and need to display them one by one, like in a photo viewer. I've made some research and found that when I use setTexture(), it actually copies the texture into the internal one (is that correct?). So, is it better to store a set of textures and call setTexture every time, or a collection of Pictures and change them?
#3
Quote from: cg923 on 09 April 2024, 19:31:13doesn't your original problem disappear
Actually, it doesn't. If get() throws the exception that isn't caught, the program will terminate and in the terminal I will be able to see what happened (what was the reason to terminate) whereas a nullptr dereference will cause a segfault without any explanation.
#4
Quote from: texus on 09 April 2024, 19:25:22make the first parameter a template
Oh, that's even better. Thank you for your advice!
#5
Thank you for your reply, texus. I assume that in my case the best way to help myself is to write some wrapper functions, e.g.
        template <class WidgetType>
        typename WidgetType::Ptr get(tgui::Gui &gui,const String& widgetName) const
        {
            auto ptr=gui.get<WidgetType>(widgetName);
            if(ptr==nullptr) throw std::runtime_error("reason+widgetName");
            return ptr;
        }
+ the same function which is overloaded for tgui::Container* instead of tgui::Gui.
#6
Quote from: cg923 on 08 April 2024, 18:50:18For example, I might want to add a widget if get() returns nullptr, or something like that.
I can also do this in case of an exception being thrown, can't I? Anyway we have already discussed that using exceptions might break backwards compatibility, so the only thing I would be glad to see is some information in the terminal.
Quote from: cg923 on 08 April 2024, 18:50:18might be annoying
I admit that it might be, but isn't it annoying to spend time using a debugger only to figure out that there was a mistake in the naming? As Texus has suggested, we can use a global flag to disable these messages (or we may not print them in the release version of the library, but do it in the debug one).
#7
I agree that it is not actually an error, but get() is almost always used to retrieve a known widget, so I have already mentioned that it's illogical to do a nullptr check and, consequently, we may not notice this error. However, if there is an intention to call get() using a name given by the user, for example through user input, then I will perform that check regardless. Moreover, in the context of get(), Gui behaves like a container (similar to std::map), and some behavior is expected when accessing out-of-range values. Additionally, using a debugger to locate such errors makes development harder. Therefore, my opinion is that get() should, at least print something to the terminal. I appreciate your suggestion about using a global flag, and I believe it is a good solution. Throwing an exception seems like a more modern approach to using C++. But anyway the final decision rests with you. Would you be so kind as to notify me later about your findings here?
#8
Well, I understand your worries about backwards compatibility, but maybe it would be a good idea to print out something with cerr/clog, for example "Widget <name> not found" to inform the developer? SFML does that and sometimes such messages clarify the details.
IMHO, some feedback is needed in these cases. Since we can't catch these errors during compilation, we must be able to detect them at runtime without causing an abnormal termination (or at least we should know why this happened).
#9
Actually, the debugger didn't give me the exact address but there was a variable with 0x0 address (pic->get()->0x0), but I needed to look through the local variables (or start gdb in a terminal) to see it. It was not quite obvious until you pointed it out. I admit that it works as it should, but I suppose that the more practical approach would be to throw an exception in order to save time in the debugger.
Moreover it's illogical to check whether get() returns nullptr if I definitely know that I've put the Widget into the gui
#10
If there is an error in the name of a widget and we try to access it, we will get a segmentation fault without any explanation. Sometimes, it can be difficult to determine whether the problem is actually in the naming, e.g.:
gui.add(picture, "picture");
//...
func(gui.get<...>("picturW")); //(1)

//////////
func(Picture::Ptr pic):
     pic->getRenderer()->setTexture(texture); //(2) We will get a segmentation fault only there!
//And in my case I truly believed that the problem was with the setTexture() function

So, my proposal is to throw an exception like std::out_of_range at the step marked as (1).
#11
Now I've got that, thank you for your comprehensive explanation. I thought that tgui::Texture is something like a container for pixels and it doesn't depend on a backend implementation but it turned out that it actually does. I truly appreciate your help and your work!
#12
Quote from: texus on 06 April 2024, 22:18:37That assertion means you are trying to create the Texture before the Gui has been constructed.
oh, yes, I haven't updated the page and haven't noticed your reply, but why do I need some backend to create a texture?
#13
Hello, the following line of code gives me a segmentation fault during execution and I don't know why:
texture.loadFromPixelData(smg.getSize(), smg.getPixelsPtr());
//smg - sf::Image;
//texture - tgui::Texture;
I definitely know that sf::Image is loaded correctly and is not empty.
The call stack:
tgui::Backend::createTexture() (Unknown:0)
tgui::Texture::loadFromPixelData(tgui::Vector2<unsigned int>, unsigned char const*, tgui::Rect<unsigned int> const&, tgui::Rect<unsigned int> const&, bool) (Unknown:0)
Backend::GetTextureFromClipboard() (Backend.hpp:37)
main() (test.cpp:41)
UPD: I've rebuilt tgui with debug flag and I have the following message from tgui::getBackend():
TGUI assertion: getBackend() was called while there is no backend
test: /.../LIBS/TGUI-1.2.0/src/Backend/Window/Backend.cpp:77: std::shared_ptr<tgui::Backend> tgui::getBackend(): Assertion `globalBackend != nullptr' failed.

Okay, I've got the idea. I must have some backend (i.e. tgui::Gui), but why?
#14
Okay, thank you a lot!
#15
Hello, I want to change SpinControl value without calling onValueChange(), is it possible?
Let me describe what I intend to do and possibly you will give some idea how to implement this.
I have 2 SpinControl widgets (the width and the height of the picture) which are linked/bound (idk which word is more correct here), so changing one should affect another, e.g. if I double height, the width should also be doubled. Let's call the function which is responsible for that BalanceRatio():
//Briefly
BalanceRatio()
{
SpindleControl2->setValue(BalancedValue);
}

When I call it inside onValueChange() it creates a recursion and it's quite logical.
Then I've made the next trick (looks ugly but it actually helped):
SpindleControl1->onValueChange([](){
//Some code here
SpindleControl1->setFocused(0);
});

SpindleControl1->onUnfocus(BalanceRatio);
And it worked pretty nice until I noticed that if I press the arrow continuously, onUnfocus will be never called.
And the question is: how to set the new value without calling onValueChange() to avoid the recursion?
P.S. I'm sorry if there are some grammar mistakes but I feel really fatigued and have neither time nor the desire to use the translator to check my writing   :-\ .
#16
Much obliged, Texus!
#17
Hello, I would like to ask if there are any ways to fully fit the picture with the constant w/h-ratio inside the panel (see attachment: the purple border is the panel and the green rectangle is the picture) that are already implemented inside the library, or should I implement such things by myself? The main idea is to fit it dynamically (while the panel is being resized from (w0;h0) to (w1; h1)).
#18
Okay, thank you for your comprehensive answer!
#19
Hello, I want to load the font after creating tgui::Font object, but I looked through the documentation and there are no such functions as loadFromFile() or loadFromMemory(). So I decided to do the following:
tgui::Font font;
font.getBackendFont()->loadFromFile("font.ttf");
but this leads to a segmentation fault. Are there any ways to do what I intend to do?
#20
Quote from: texus on 25 March 2024, 18:24:54all TGUI widgets need to be destroyed before the Gui object is destroyed.
Oh, that's it. I swapped two lines in the code (see below) and it settled the matter, thank you!
//How it was:
Scene scene;
tgui::Gui gui;

//How it is now:
tgui::Gui gui;
Scene scene;
#21
Hello, I suppose that I'm missing something but can't figure out what. I have the next class (some realization nuances are omitted):
class Scene
{
public:
    std::list<tgui::Group::Ptr> groups;
private:
    using iterator = std::list<tgui::Group::Ptr>::iterator;
    iterator current_group;
    void change_scene(iterator &from, iterator &to);

};

In the main function I have something like that:

scene.groups.emplace_back(tgui::Group::create());

//Some widgets initialization and adding them to the group

gui.add(scene.groups.begin());
It works pretty nice until I close the program (and ~Scene() is called) and get Seg fault message. I've attached the picture from the debugger.
#22
Thank you, now it works!
#23
Hello!
What I'm supposed to do: when button was clicked its texture should be changed.
I have textures in one single .png file and my code looks like:
bool linked = 1;
    tgui::Texture link_t[2];
    for (short i = 0; i < 2; ++i)
        link_t[i].load("lu.png", {unsigned(50 * i), 0, 50, 50});

    auto link_b = gui.get<tgui::Button>("link_b");

    auto lb_func = [&link_b, &linked, &link_t]()
    {
        linked = !linked;
        link_b->getRenderer()->setTexture(link_t[linked]);
    };

    gui.get<tgui::Button>("link_b")->onClick(lb_func);
It's expected the texture to be changed every time I click the button, but actually it changes only once.

So I've written the following code to "separate" textures:
bool linked = 1;
    tgui::Texture linked_t, unlinked_t;

    linked_t.load("linked.png");
    unlinked_t.load("unlinked.png");

    auto link_b = gui.get<tgui::Button>("link_b");

    if (linked)
        link_b->getRenderer()->setTexture(linked_t);
    else
        link_b->getRenderer()->setTexture(unlinked_t);

    auto lb_func = [&link_b, &linked, &linked_t, &unlinked_t]()
    {
        linked = !linked;
        if (linked)
            link_b->getRenderer()->setTexture(linked_t);
        else
            link_b->getRenderer()->setTexture(unlinked_t);
    };

    gui.get<tgui::Button>("link_b")->onClick(lb_func);
And it works pretty good! I think the problem that my first piece of code uses the textures with the same ID. Perhaps, that's the reason why setTexture() doesn't change the texture.
#24
Okay, thank you. I have also found a bug with dynamic texture changing. Should I start a new topic, or can I describe it here?
#25
Version: TGUI-1.1.0
OS: Kubuntu-22.04

Hello, I've faced the following problem:
When I call spin_control->hideWithEffect(...) none of the effects affects widget somehow.
 
When I call spin_control->getRenderer()->setOpacity(0) nothing happens again.

But if I use
spin_control->getSpinButtonRenderer()->setOpacity(0.5);
spin_control->getSpinTextRenderer()->setOpacity(0.5);
it actually works.

Is this bug or am I doing something wrong?