scrollbar tutorials?

Started by wmbuRn, 15 July 2013, 03:46:29

texus

QuoteSo
tgui::Scrollbar::Ptr scrollbar(*Group1);

Doesnt work, when i change values of scrollbar [with mouse or mouse scroll] program crashes with
/usr/local/include/TGUI/SharedWidgetPtr.hpp:271: T* tgui::SharedWidgetPtr<T>::operator->() const [with T = tgui::Panel]: Assertion `m_WidgetPtr != __null' failed.
You are doing something with a null pointer. At first I was a bit surprised because I though this crash came from inside tgui, but I think the problem lies in your scrollbarValueChanged function.
Do you have code like "gui->get("Scrollbar")" there or something like that?

Because what I notice is that when you pass 'gui' to it you also give the widget a name, but when you pass '*Group1' to it you don't give it a name.
So if it is the problem that I suspect than you just need "tgui::Scrollbar::Ptr scrollbar(*Group1, "Scrollbar");".

Although I don't see why the scrollbar should be inside the panel instead of just in the gui.

Quoteexcept i see scrollbar in panel where i dont need scrollbar
What exactly do you mean with this?

QuoteNeed to figure out how to access each editBoxes to read it values, and to modify them.
You can get them back later with the get function on your Group1.

But make sure all widgets have unique names.
If you are still creating the pictures as before then you are going to get name conflicts.
You are calling your pictures "1", "2", "3", "4", ...
But you are also calling your edit boxes "1", "2", "3", "4", ...

So maybe you should write
Code (cpp) Select
tgui::EditBox::Ptr Name(*Group1, "EditBox" + tgui::to_string(i));
Like this, your edit boxes will be named "EditBox1", "EditBox2", "EditBox3", ...
And you can get them from Group1 later with this name.

If you would have two widgets with the same name then getting them from Group1 will only give you the first occurence (first added widget with that name), and it will be impossible to access the other widget.

wmbuRn

#16
Currently i have 3 panels. mainScreen, loginScreen, and Group1. With "tgui::Scrollbar::Ptr scrollbar(gui, "Scrollbar");" i see scrollbar in Group1, loginScreen and mainScreen and i dont need scrollbar on panels loginScreen and mainScreen. Will try autohide(). On each panel will access to scrollbar and will set value greater than max Value and hopefully scrolbar will be hidden on those 2 panels. A good chance to learn something new. :)

QuoteDo you have code like "gui->get("Scrollbar")" there or something like that?

No, i am still using your scrollbarValueChanged function. Need to change code inside it. I have some widgets i want to move and some i dont want to move. I know how to set some widgets to move and some not to move. So i will fix widgets, except for scrollbar.

Quotetgui::Scrollbar::Ptr scrollbar(*Group1, "Scrollbar");

Causes the crash with same code i posted before, and i have:

for (unsigned int i = 0; i < widgets.size(); ++i)
    {
            if (widgetNames[i] != "Scrollbar")
            widgets[i]->move(0, scrollbarValue - callback.value);
    }

Inside scrollbarValueChanged() . Thats what confuzed me. Everything from Group1 works except for scrollbar. i will work on it :)


Edit:
"tgui::EditBox::Ptr Name(*Group1, "EditBox" + tgui::to_string(i));" works, i can access to what is written in EditBox. Since i can access to whats is written inside EditBox i can store that information into .txt file, sql databases or object files. Also i can copy what is written inside one Group into another Group. 
I added 4th panel. Scrollbar is not working there. It is visible but it wont scroll widgets. so i def. need to set  "tgui::Scrollbar::Ptr scrollbar(*Group1);"
, "tgui::Scrollbar::Ptr scrollbar(*Group2);" In different panels.

texus

I see two solutions for the scrollbar.
- You have the scrollbar directly in the gui. When loginScreen or mainScreen is visible, you call scrollbar->hide() and when Group1 becomes visible again you call scrollbar->show().
- You make a different scrollbar inside every groups that need it. This will allow every scrollbar to have its own callback function and to do different things in every group.

The reason why your Group2 doesn't react on the scrollbar, is that you access Group1 in scrollbarValueChanged.
If you could find a way to access the current group, e.g. holding some string that contains either "Group1" or  "Group2" and then use the string like this:
tgui::Panel::Ptr panel = callback.widget->getParent()->get(theString);
Then you can keep the scrollbar in your gui and it will be able to scroll the widgets in whatever group you want by just adjusting the string.

wmbuRn

#18
Quote- You make a different scrollbar inside every groups that need it. This will allow every scrollbar to have its own callback function and to do different things in every group.

Thats what i was thinking, except

tgui::Scrollbar::Ptr scrollbar(*Group1, "Scrollbar");
    scrollbar->load("Data/Buttons/Black.conf");
    scrollbar->setLowValue(600);
    scrollbar->setMaximum(3400);
    scrollbar->setSize(15, 530);
    scrollbar->setPosition(785, 0);
    scrollbar->bindCallbackEx(scrollbarValueChanged, tgui::Scrollbar::ValueChanged);


Crashes the program with:

/usr/local/include/TGUI/SharedWidgetPtr.hpp:271: T* tgui::SharedWidgetPtr<T>::operator->() const [with T = tgui::Panel]: Assertion `m_WidgetPtr != __null' failed.
Aborted (core dumped)


I am using your function for scrollbarValueChanged:

void scrollbarValueChanged(const tgui::Callback& callback)
{
tgui::Panel::Ptr Group1 = callback.widget->getParent()->get("Group1");

    // Reposition the object
    std::vector<tgui::Widget::Ptr> widgets = Group1->getWidgets();
    std::vector<sf::String> widgetNames = Group1->getWidgetNames();
    for (unsigned int i = 0; i < widgets.size(); ++i)
    {
            if (widgetNames[i] != "Scrollbar")  // even if i change this same thing happend.
            widgets[i]->move(0, scrollbarValue - callback.value);
    }

    scrollbarValue = callback.value;
}

texus

Right before this line
tgui::Scrollbar::Ptr scrollbar(*Group1, "Scrollbar");
add
std::cout << Group1.get() << std::endl;

On top of your scrollbarValueChanged function add
std::cout << callback.widget << std::endl;
std::cout << callback.widget->getParent() << std::endl;
std::cout << callback.widget->getParent()->get("Group1") << std::endl;


And perhaps add this inside the for loop in scrollbarValueChanged
std::cout << widgets[i].get() << std::endl;

Is any of the things that get printed a null pointer?
The error means that you are calling a function on some null pointer, so somewhere, something isn't initialized properly.

wmbuRn

std::cout << callback.widget->getParent()->get("Group1") << std::endl;

Is not working, i get this error >> error: no match for 'operator<<' in 'std::cout << tgui::Container::get(const sf::String&) const((* & sf::String(((const char*)"Group1"), (*(const std::locale*)(& std::locale())))))'

So i removed that line. I used these lines:

std::cout << "callback.widget: " << callback.widget << std::endl; // at the beggining of     
                                                                                                           //scrollbarValueChanged

std::cout << "callback.widget->getParent() : " << callback.widget->getParent() << std::endl;
std::cout << "widgets[i].get(): " << widgets[i].get() << std::endl; // this one is inside
                                                                                                           // for loop  scrollbarValueChanged

std::cout << "Group1.get(): " << Group1.get() << std::endl;    // before Scrollbar


Here is the output:

Group1.get(): 0x9858978
callback.widget: 0x985a990
callback.widget->getParent() : 0x9858a40
Swing Studio 0: /usr/local/include/TGUI/SharedWidgetPtr.hpp:271: T* tgui::SharedWidgetPtr<T>::operator->() const [with T = tgui::Panel]: Assertion `m_WidgetPtr != __null' failed.
Aborted (core dumped)


texus

The line should be
std::cout << callback.widget->getParent()->get("Group1").get() << std::endl;
(which prints the real internal pointer instead of my smart pointer class)

Wait, you made the scrollbar part of Group1 right?
That line assumes that scrollbar is part of the gui. It first asks for the parent (which is supposed to be gui) and then search for the panel called "Group1". But your scrollbar is part of Group1, so when accessing the parent, you already find Group1 and you thus no longer have to search for it.

So change
tgui::Panel::Ptr Group1 = callback.widget->getParent()->get("Group1");
into
tgui::Panel* Group1 = callback.widget->getParent();

As you can see sometimes have to use a normal pointer (*) and sometimes my smart pointer (::Ptr).
This is still a bit of a problem in tgui, but I'll look into this so that in the future everything should work with these smart pointers.

wmbuRn

#22
I tried both, scrollbar being (gui, "Scrollbar) and being (*Group1, "Scrollbar).

With being

tgui::Scrollbar::Ptr scrollbar(gui, "Scrollbar");


I have plenty of output from

std::cout << "widgets[i].get(): " << widgets[i].get() << std::endl;

Thats becouse Scrollbar is working as it should.


with scrollbar being (*Group1, "Scrollbar")

Group1.get(): 0xa152a30
callback.widget: 0xa4ae058
callback.widget->getParent(): 0xa152af8
Swing Studio 0: /usr/local/include/TGUI/SharedWidgetPtr.hpp:271: T* tgui::SharedWidgetPtr<T>::operator->() const [with T = tgui::Panel]: Assertion `m_WidgetPtr != __null' failed.
Aborted (core dumped)


After adding your code, and scrollbar(*Group1, "Scrollbar")

std::cout << callback.widget->getParent()->get("Group1").get() << std::endl;

I have this output:

Group1.get(): 0x93e9b18
callback.widget: 0x9745140
callback.widget->getParent(): 0x93e9be0
getParent()->get(group1): 0
Swing Studio 0: /usr/local/include/TGUI/SharedWidgetPtr.hpp:271: T* tgui::SharedWidgetPtr<T>::operator->() const [with T = tgui::Panel]: Assertion `m_WidgetPtr != __null' failed.
Aborted (core dumped)


After adding your code, and scrollbar(gui, "Scrollbar")

std::cout << callback.widget->getParent()->get("Group1").get() << std::endl;

I have this output:

callback.widget: 0xa4d3010
callback.widget->getParent(): 0xbf94ed34
getParent()->get(group1): 0xa1779e8
widgets[i].get(): 0xa178cb0
widgets[i].get(): 0xa178f58
widgets[i].get(): 0xa171dd0
widgets[i].get(): 0xa172860
widgets[i].get(): 0xa1733e8
widgets[i].get(): 0xa173ec0
  // and more widgets[i] output here




With:

tgui::Panel* Group1 = callback.widget->getParent();

i get this error:

error: invalid conversion from 'tgui::Container*' to 'tgui::Panel*' [-fpermissive]


Do you want me to upload entire project? After its done it will be opensource anyway :) [except encryption will be removed] :)

texus

Then just use Container* instead of Panel*. Right now I'm just writing example code, not necessary something that can be compiled.

wmbuRn

#24
Container* works as it should. Thank you.

Scrollbar is part of (*Group1). Off to make more Groups and to continue working on this app :)

Added another group, another Scrollbar another scrollbarValueChangedGroup2, bindEx the new scrollbar and it is working. So thank you very much :)