I am new to coding, a few months with Python and trying to wrap my head around Kivy. I think there is a simple solution to this but I am struggling when it comes to calling a method in one class from another. Not even sure if this is possible, my OOP wouldn't be very strong!!
Would appreciate if someone could explain this to me. I've looked online but still struggling to understand what I need to do.
i have a simple code that had a label and 3 toggle buttons, the label text changes to show how many toggle buttons are pressed. Below is the original code.
What I am trying to do create the toggle buttons using a loop so that the number of toggle buttons can be easily altered. i have achieved this but when I try and bind the method to the toggle button the code fails with. I also tried defining a method within the "Tbtn" class to call the Main.Counter() but this didn't work either.
The line
self.bind(on_state = Main.counter())
in the init of the toggle button is where i am going wrong I think.
Any help and even an explanation would be great. Not the first time I have been stuck on this!! Thanks
Original Code:
from kivy.app import App
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
class Tbtn(ToggleButton):
pass
class Header_Box(BoxLayout):
pass
class Counter(BoxLayout):
pass
class Main(BoxLayout):
count = NumericProperty()
def counter(self,widget):
toggles = []
for child in self.ids.Seat_Box.children:
if isinstance(child, ToggleButton):
if child.state == 'down':
toggles.append(child.text)
self.count = len(toggles)
print(self.count)
class TestApp(App):
def build(self):
return Main()
TestApp().run()
The KV file:
<Main>:
name: "main"
BoxLayout:
orientation: "vertical"
Header_Box:
Label:
text: str(root.count)
Counter:
id: Seat_Box
Tbtn:
id: btn1
on_state: root.counter(self)
Tbtn:
id: btn2
on_state: root.counter(self)
Tbtn:
id: btn2
on_state: root.counter(self)
Code with for Loop:
from kivy.app import App
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
class Tbtn(ToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(on_state = Main().counter())
class Header_Box(BoxLayout):
pass
class Counter(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for x in range(3):
btn = Tbtn()
self.add_widget(btn)
class Main(BoxLayout):
count = NumericProperty()
def counter(self,widget):
toggles = []
for child in self.ids.Seat_Box.children:
if isinstance(child, ToggleButton):
if child.state == 'down':
toggles.append(child.text)
self.count = len(toggles)
print(self.count)
class TestApp(App):
def build(self):
return Main()
TestApp().run()
KV file:
<Main>:
name: "main"
BoxLayout:
orientation: "vertical"
Header_Box:
Label:
text: str(root.count)
Counter:
id: Seat_Box
Firstly, Remove self.bind(on_state = Main().counter())
.
I suggest you to solve this in.kv side.
Way 1-.kv side: Add this below your.kv file:
<Tbtn>:
on_state: app.get_running_app().root.counter(self)
Way 2-.py side: Add this in Tbtn class.
def on_release(self):
App.get_running_app().root.counter(self)
Although the other answer already solved your issue, the following made me post this one.
Any help and even an explanation would be great...
Technically the following line,
self.bind(on_state = Main().counter())
is wrong for various reasons. Let's try to figure this out.
The method on_state
is kind of generic one not a default event (like on_press
etc.). That's why bind(on_state = some_callback)
won't work.
Again you did Main().counter()
which actually creates a new instance of Main
(which may or may not be related to the root
, and here it's of course not) and assigned to its method.
It seems you want to just access one of Main
widget's (which happens to be the root
widget here) method.
Since you used kvlang
, this could be done more efficiently as follows,
<Tbtn>:
on_state: app.root.counter()
You can find more about this in the kvlang
doc .
Now in .py
you just define the class along with some other changes,
class Tbtn(ToggleButton):
pass
.
.
.
class Main(BoxLayout):
count = NumericProperty()
def counter(self): # Pass no extra args as you haven't done in 'on_state' method.
toggles = []
.
.
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.