Reputation: 163
I'm writing a kivy app and I want to keep the layout and the controller separate. Here is the sample code of what I'm trying to accomplish:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
class AppLayout(BoxLayout):
def __init__(self, **kwargs):
super(AppLayout, self).__init__(**kwargs)
self.orientation = 'vertical'
self.padding = [10, 10, 10, 10]
self.text_bar = TextInput(hint_text='Write Something',
multiline=False,
padding=[5, 5, 5, 5],
font_size=20,
size_hint=(0.8, 1))
self.button = Button(text="Do Something",
size_hint=(0.2, 1))
self._text_bar_box = BoxLayout(pos_hint={'top': 1},
size_hint=(1, 0.04),
orientation='horizontal')
self._text_bar_box.add_widget(self.text_bar)
self._text_bar_box.add_widget(self.button)
self.add_widget(self._text_bar_box)
self.label = Label(text="Your text will be displayed here", font_size=20)
self._big_box = BoxLayout(padding=[10, 10, 10, 10],
size_hint=(1, 0.65))
self._big_box.add_widget(self.label)
self.add_widget(self._big_box)
class AppController:
def __init__(self, app_layout: AppLayout):
super(AppController, self).__init__()
self.app_layout = app_layout
self.app_layout.search_button.bind(on_press=self.get_string)
def get_string(self):
self.app_layout.label.text = self.app_layout.text_bar.text
class MainApp(App):
def build(self):
app_layout = AppLayout()
AppController(app_layout)
return app_layout
if __name__ == "__main__":
MainApp().run()
This is how the gui appears:
When I press the
button
the text in the text_bar
is not displayed in the label. How can I accomplish this?
Upvotes: 1
Views: 626
Reputation: 5177
There are a few other issues with the example you posted, however what really breaks it is that here
class MainApp(App):
def build(self):
app_layout = AppLayout()
AppController(app_layout)
return app_layout
the instance of AppController
gets garbage collected immediately. Save it as a property of MainApp
:
self.controller = AppController(app_layout)
Edit: Full example
The callback expects one extra argument,instance
: the object that fired the event.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
class AppLayout(BoxLayout):
def __init__(self, **kwargs):
super(AppLayout, self).__init__(**kwargs)
self.orientation = 'vertical'
self.padding = [10, 10, 10, 10]
self.text_bar = TextInput(hint_text='Write Something',
multiline=False,
padding=[5, 5, 5, 5],
font_size=20,
size_hint=(0.8, 1))
self.button = Button(text="Do Something",
size_hint=(0.2, 1))
self._text_bar_box = BoxLayout(pos_hint={'top': 1},
size_hint=(1, 0.04),
orientation='horizontal')
self._text_bar_box.add_widget(self.text_bar)
self._text_bar_box.add_widget(self.button)
self.add_widget(self._text_bar_box)
self.label = Label(text="Your text will be displayed here", font_size=20)
self._big_box = BoxLayout(padding=[10, 10, 10, 10],
size_hint=(1, 0.65))
self._big_box.add_widget(self.label)
self.add_widget(self._big_box)
class AppController:
def __init__(self, app_layout= AppLayout):
self.app_layout = app_layout
self.app_layout.button.bind(on_press=self.get_string)
def get_string(self, *args):
self.app_layout.label.text = self.app_layout.text_bar.text
class MainApp(App):
def build(self):
app_layout = AppLayout()
self._controller = AppController(app_layout)
return app_layout
if __name__ == "__main__":
MainApp().run()
Upvotes: 2