I'm creating a button in StackLayout in file info_options.kv
. Now I want to call a function in class InfoOptionsPanel
whenever this button is pressed. I'm able to call this funtion when I'm replacing return MainPanel()
with return InfoOptionsPanel()
i.e. when I'm not using the layout created by MainPanel
, but when I'm using MainPanel
class for gui then button gives below, also note that there is no problem in GUI even when using MainPanel
for GUI.
error thrown
File "C:\Users\..\AppData\Local\Programs\Python\Python312\Lib\site-packages\kivy\lang\builder.py", line 60, in custom_callback
exec(__kvlang__.co_value, idmap)
File "K:\path\to\project\Info_options.kv", line 5, in <module>
on_press: self.parent.on_press()
^^^^^^^^^^^^^^^^
AttributeError: 'InfoOptionsPanel' object has no attribute 'on_press'
info.kv
<InfoPanel@BoxLayout>
orientation: 'vertical'
size_hint_y: 0.8
pos_hint: {"top": 1}
Label:
id: info_label
text:"Click button"
font_size:50
info_options.kv
<InfoOptionsPanel@StackLayout>:
orientation: 'lr-tb'
Button:
text: 'Button'
on_press: self.parent.on_press()
size_hint :.7, 0.1
main_screen.kv
<MainPanel@BoxLayout>:
orientation: 'vertical'
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
InfoPanel:
size: 100, 100
AnchorLayout:
anchor_x: 'right'
anchor_y: 'bottom'
InfoOptionsPanel:
size: 100, 100
main.py
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
import os
kivy_design_files = ["Info_options", "Info", "main_screen",]
for kv_file in kivy_design_files:
Builder.load_file(os.path.join(os.path.abspath(os.getcwd()), kv_file + ".kv"))
class InfoPanel(BoxLayout):
pass
class InfoOptionsPanel(StackLayout):
def on_press(self):
print("Button pressed\n"*55)
class MainPanel(BoxLayout):
pass
class MyApp(App):
def build(self):
return MainPanel()
if __name__ == '__main__':
MyApp().run()
You don't need to inherit from Kivy's layout classes in both main.py
and kivy files. Either remove inheritance from main.py
or from your kivy files.
For main.py
,
class InfoPanel(): # don't inherit from BoxLayout
pass
class InfoOptionsPanel(): # don't inherit from StackLayout
def on_press(self):
print("Button pressed\n"*55)
class MainPanel(): # don't inherit from BoxLayout
pass
Or for kivy files (do the same in each),
<InfoOptionsPanel>: # removed @StackLayout
orientation: 'lr-tb'
Button:
text: 'Button'
on_press: root.on_press()
size_hint :.7, 0.1
I would suggest you to remove inheritance from main.py and keep python code nice and clean. Kivy files are meant to deal with UI, so take advantage of that.
Also, use root.on_press()
instead of self.parent.on_press()
. Both will work regardless, but root
clarifies that you're referring to the root widget. self.parent
would refer to some other widget if you add multiple parent widgets or layouts to Button
in the future.