TabbedPanel - current tab changes binding

1,171 views
Skip to first unread message

Goffrey

unread,
Nov 28, 2012, 12:32:32 PM11/28/12
to kivy-...@googlegroups.com
Hi everyone.

Is there a way for TabbedPanel to get something like 'on_current_tab' event - when content of current tab has changed to another one?

I want to update some properties based on what tab is actually selected. I tried to bind it through TabbedPanelHeader.bind(state=state_cb) (since it inherits from ToggleButton). Which sort of works, but I found out that state is changed before content switching, so in my callback, I get acces to 'previous' current_tab. I was thinking to bind something else.. but cannot get the idea.


Thanks for suggestions.


Gabriel Pettier

unread,
Nov 28, 2012, 2:04:21 PM11/28/12
to kivy-...@googlegroups.com
Well, current_tab is a property, right? :) so you can bind to it.

TabbedPanelHeader.bind(current_tab=current_tab_cb)


should do it :)
--
 
 

Message has been deleted

Goffrey

unread,
Nov 28, 2012, 3:45:53 PM11/28/12
to kivy-...@googlegroups.com
Thanks for fast reply.

Well, you're right (only current_tab is property of TabbedPanel, not TabbedPanelHeader, but I get the point). And I think I also tried it. The problem is it does nothing.. so maybe I have some stupid mistake, here is my code:

class Plane(TabbedPanel):
    def __init__(self, **kwargs):
        super(Plane, self).__init__(**kwargs)
        s
elf.bind(current_tab=self.contentChanged_cb)
        # also tried content, nothing happened again
        # self.bind(content=self.contentChanged_
cb)

    def contentChanged_cb(self, obj, value):
        print 'CHANGE'


So I'm adding more TabbedPanelHeader objects, clicing on them.. and  getting no printing.

Dne středa, 28. listopadu 2012 20:04:21 UTC+1 tshirtman napsal(a):

Gabriel Pettier

unread,
Nov 28, 2012, 4:26:59 PM11/28/12
to kivy-...@googlegroups.com
Sorry, i should have checked, there is no dispatch of event when
current_tab changes, your code is correct, i think this is an issue.
Looking for a solution.
> --
>
>


Gabriel Pettier

unread,
Nov 28, 2012, 5:04:01 PM11/28/12
to kivy-...@googlegroups.com
Ok, this is fixed in latest master, if you are not using the git
version, you can manually update your version, the patch is rather short.

https://github.com/kivy/kivy/commit/52b54b16d6fc3b794e0dcd1c05fc7602aa88178a

with that, binding to current_tab works.

Goffrey

unread,
Nov 29, 2012, 10:56:26 AM11/29/12
to kivy-...@googlegroups.com
Good Guy Tshirtman:)

Thanks. Yep, working properly now. I'm sort of glad it was an issue, cause I didn't want to ask too simple question, but I already tried few thinks..

And when we are already on that topic. I have a couple of questions. Shouldn't it work also for content? It is also TabbedPanel's Object property..
And what about on_default_tab event? It is mentioned in docu, but it's not reacting for me. For pretty same example:

class Plane(TabbedPanel):
    def __init__(self, **kwargs):
        super(Plane, self).__init__(**kwargs)
        self.bind(content=self.contentChanged_cb)
        self.bind(on_default_tab = self.my_default_tab_callback)  


    def contentChanged_cb(self, obj, value):
        print 'CONTEENT'
    def my_default_tab_callback(self, obj, value):
        print 'DEFAUUULT'


Again, no printing. And when should on_default_tab fired? When it's active? When it's changed?

Dne středa, 28. listopadu 2012 23:04:01 UTC+1 tshirtman napsal(a):

Gabriel Pettier

unread,
Nov 29, 2012, 2:54:55 PM11/29/12
to kivy-...@googlegroups.com
Hi, sorry for late answer,

for content, it's a bit counterintuitive, but it's actually the container in which the tab content will be put, so you could do

self.content.bind(children=callback)

but that won't work if content is still None, so it's better to do that in two times:

class Plane(TabbedPanel):
    def __init__(self, **kwargs):
        super(Plane, self).__init__(**kwargs)
        self.bind(content=self.content_changed_cb)

    def content_changed_cb(self, obj, value):
        self.content.bind(children=self.on_switch)

    def on_switch(self, *args):
        print "!!!"

should work.
--
 
 

Akshay Arora

unread,
Nov 29, 2012, 4:05:17 PM11/29/12
to kivy-...@googlegroups.com
Hello Geoffrey,

The fact that tabbedpanel.content is a container in which the current tabs content is put should be made more clear in the documentation.

You should checkout.
As for monitoring the change to the content area of the Tabbed Panel you can do what Gabriel suggested. Also simply binding to the `current_tab` should let you access the current content of the tabbedpanel. There are also a few other methods that I'll just highlight through code.


from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder

Builder.load_string('''
<MyClass>:
    default_tab_text: "Oy!"
    TabbedPanelItem:
        text: 'test'
        id: tpitem
        Button:
            text: "change def tab"
            id: my_button
            on_release:
                root.default_tab = tpitem
    TabbedPanelItem:
        text: '2'
        TextInput:
''')

class MyClass(TabbedPanel):

    def __init__(self, **kwargs):
        super(MyClass, self).__init__(**kwargs)
        # bindings are usually for when using objs without having to subclass
        # you can simply bind like so::
        # obj = TabbedPannel()
        # obj.bind(current_tab=my_func)
        self.bind(current_tab=self.contentChanged_cb)
        # This part should be fixed in the doc now, bind to `default_tab` not
        # `on_default_tab`, sry for that.
        self.bind(default_tab = self.my_default_tab_callback)

    def on_default_tab(self, instance, value):
        # As we are inheriting from TabbedPanel we can simply
        # override on_<propname> function without having to bind
        print "default_tab changed to ", value

    def switch_to(self, header):
        # you can also just override switch_to without having to
        # do anything else and check for header.content.
        # However this will only work when you are overriding the class
        # don't forget to call the base function as we aren't overriding
        # functionality of switching tab
        super(MyClass, self). switch_to(header)
        print 'switch_to, content is ', header.content

    def contentChanged_cb(self, obj, value):
        print 'CONTEENT', value.content


    def my_default_tab_callback(self, obj, value):
        print 'DEFAUUULT'

class MainApp(App):

    def build(self):
        return MyClass()

if __name__ == '__main__':
    MainApp().run()

The changes for default_tab and the doc fixes are in `tp` branch.
To Test::

    git pull
    git checkout tp

Test with the provided code.

Hope that helps.

--
 
 

Goffrey

unread,
Nov 29, 2012, 7:16:41 PM11/29/12
to kivy-...@googlegroups.com
I tried your code and it's working fine. Now it's clear. In my case, binding current_tab is sufficient, but I was just curious about the rest.

Thanks again, to both of you;)

Dne čtvrtek, 29. listopadu 2012 22:05:17 UTC+1 qua-non napsal(a):
Reply all
Reply to author
Forward
0 new messages