I'm trying KivyMD to build an app and everything was working great until I ran into an issue which I can't seem to fix even after spending an entire day on it yesterday. I'm building an app in which I can store my workouts and ran into an issue when addeding two MDTextFields. First they wouldn't align properly and they moved all the way outside the boxlayout, then after some resizing (self.minimum_height in the KV file) they are now clickable (you can see the hint text changing), but they won't allow for any input. Can you anyone help me why the MDTextField aren't working? My guess it has something to do with the same issue which caused the fields to be moved outside the boxlayout, but I don't understand what is causing that issue.
Here is the modified KV:
NavigationLayout:
id:nav_layout
MainAppScreenManager:
id: screen_manager
AddWorkoutMenu:
<MainAppScreenManager>
<AddWorkoutMenu>
name: "addworkoutmenu"
id: "addworkoutmenu"
workoutname:workoutname
setlist:setlist
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "Add Workout"
elevation: 10
MDTextField:
id: workoutname
hint_text: "Workout name"
ScrollView:
MDList:
id: setlist
Sets:
id: workoutboxlist
MDRoundFlatIconButton:
id:addset
icon: "plus"
text: "Add set"
on_release:
root.add_set()
<Sets>
id:workoutbox
workoutexerciselist:workoutexerciselist
addbutton:addbutton
reps:reps
rest:rest
orientation: "vertical"
md_bg_color: app.theme_cls.primary_color
radius: 15, 15, 15, 15
padding: "16dp"
spacing: "4dp"
size_hint_y: None
height: self.minimum_height
BoxLayout:
pos_hint: {"center_x": .5, "center_y": 0}
orientation: "horizontal"
MDLabel:
pos_hint: {"center_x": .5, "center_y": .2}
theme_text_color: "Custom"
text_color: [1,1,1,1]
text: root.id
MDIconButton:
pos_hint: {"center_x": .5, "center_y": 0}
icon: "trash-can"
theme_text_color: "Custom"
text_color: [1,1,1,1]
on_release:
self.parent.parent.remove_set()
MDBoxLayout:
size_hint_y: None
height: self.minimum_height / 4
pos_hint: {"center_x": .5, "y": 0}
orientation: "horizontal"
MDLabel:
size_hint: (0.15,None)
pos_hint: {"center_x": .5, "center_y": 0}
theme_text_color: "Custom"
text_color: [1,1,1,1]
text: "Reps:"
MDTextField:
id: reps
size_hint: (0.4,None)
pos_hint: {"center_x": .5, "center_y": 0.1}
spacing: "4dp"
current_hint_text_color: [1,1,1,1]
line_color_normal: [1,1,1,1]
hint_text: "# reps"
MDLabel:
size_hint: (0.1,None)
pos_hint: {"center_x": .5, "center_y": 0}
spacing: "4dp"
theme_text_color: "Custom"
text_color: [1,1,1,1]
text: "Rest:"
MDTextField:
id: rest
size_hint: (0.4,None)
pos_hint: {"center_x": .5, "center_y": 0.1}
spacing: "4dp"
current_hint_text_color: [1,1,1,1]
line_color_normal: [1,1,1,1]
hint_text: "in seconds"
MDList:
id:workoutexerciselist
MDRoundFlatIconButton:
id:addbutton
icon: "plus"
theme_text_color: "Custom"
text_color: [1,1,1,1]
text: "Add exercise"
on_release:
root.open_the_menu()
<WorkoutExerciseListItem>
id: listitem
theme_text_color: "Custom"
text_color: [1,1,1,1]
DeleteItem:
<DeleteItem>
name: "deleteicon"
icon: "close"
theme_text_color: "Custom"
text_color: [1,1,1,1]
on_release:
root.remove()
Here is the modified Python:
from kivymd.app import MDApp
from kivymd.theming import ThemableBehavior
from kivymd.toast import toast
from kivymd.uix.list import OneLineIconListItem, MDList, IRightBodyTouch, OneLineRightIconListItem
from kivymd.uix.menu import MDDropdownMenu, RightContent
from kivymd.uix.button import MDIconButton
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.widget import Widget
from kivy.properties import StringProperty, ObjectProperty, NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from database import DataBaseExercises, DataBaseWorkouts
class AddWorkoutMenu(Screen):
def __init__(self, **kwargs):
super(AddWorkoutMenu, self).__init__(**kwargs)
def add_set(self):
self.ids.setlist.add_widget(Sets(id = ""))
for i in self.ids.setlist.children:
if not hasattr(i, 'menu_1'):
i.create_self()
def save(self):
workout = self.workoutname.text
sets = self.ids.workoutboxlist._sets
if workout != "":
db_workouts.add(workout, sets)
self.parent.current = "workouts"
self.clear_all()
toast("Exercise saved")
else:
toast("Please fill in all information")
def clear_all(self):
self.workoutname.text = ""
for i in list(self.setlist.children):
self.setlist.remove_widget(i)
Sets._ids = 0
self.add_set()
def update_ids(self, removed, total):
if removed != total:
for i in self.ids.setlist.children:
current_number = int(i.id[-1])
if current_number > removed:
current_number -= 1
i.id = "Set " + str(current_number)
class Sets(MDBoxLayout):
_ids = 0
_sets = {}
def __init__(self, **kwargs):
super(Sets, self).__init__(**kwargs)
Sets._ids += 1
self.id = "Set " + str(Sets._ids)
self._sets[self.id] = {}
self._sets[self.id]["Exercise"] = []
self._sets[self.id]["Reps"] = []
self._sets[self.id]["Rest"] = []
def add_selection(self, name):
self.workoutexerciselist.add_widget(WorkoutExerciseListItem(text=name))
self._sets[self.id]["Exercise"].append(name)
print(self._sets[self.id]["Exercise"])
self.update_height()
def update_height(self):
if self.workoutexerciselist.height == 16.0:
self.workoutexerciselist.height = 0.0
self.height = self.minimum_height + self.workoutexerciselist.height
def create_menu(self, text, instance):
menu_items = [{"text": i} for i in text]
return MDDropdownMenu(position = "auto", caller=instance, items=menu_items, width_mult=5, callback=self.set_item)
def create_self(self):
exerciselist = db_exercise.get_all()
self.menu_1 = self.create_menu(exerciselist, self.addbutton)
def update_self(self, value):
new_list = []
new_list.append(value)
for i in self.menu_1.items:
for u in i.values():
new_list.append(u)
self.menu_1 = self.create_menu(new_list, self.addbutton)
def set_item(self, instance):
self.menu_1.on_dismiss()
self.add_selection(instance.text)
self.remove_item(instance.text)
def remove_item(self, item):
new_list = []
for i in self.menu_1.items:
for u in i.values():
if u != item:
new_list.append(u)
self.menu_1 = self.create_menu(new_list, self.addbutton)
def open_the_menu(self):
self.menu_1.open()
def remove_set(self):
number = int(self.id[-1])
self._sets.pop("Set "+str(number))
self.update_set(number)
self.id = "Set 0"
self.parent.parent.parent.parent.parent.update_ids(number, Sets._ids)
Sets._ids -= 1
self.parent.remove_widget(self)
def update_set(self, number):
for i in range(number, Sets._ids):
self._sets["Set " + str(i)] = self._sets["Set " + str(i+1)]
self._sets.pop("Set " + str(i + 1))
def save_reps_and_rest(self):
self._sets[self.id]["Reps"] = self.reps
self._sets[self.id]["Rest"] = self.rest
class WorkoutExerciseListItem(OneLineRightIconListItem):
pass
class DeleteItem(IRightBodyTouch, MDIconButton):
pass
class MainAppScreenManager(ScreenManager):
pass
class MainApp(MDApp):
pass
if __name__ == "__main__":
MainApp().run()
Not sure what is happening, but adding:
color_mode: 'custom'
line_color_focus: 1, 1, 1, 1
to each MDTextField seems to wok.
Related
I want to be able to click on MDFlatButton that says Štart and i want it to let's say for an example to call get_user_input(self) which would print whatever is inside text field. And I have been struggling with this for 2 whole days and i have no idea what to do, I am just a beginner and I have no clue what am I doing so sorry if it's messy. Ty for help, those are my files:
main.py file:
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.textfield import MDTextField
from kivy.properties import StringProperty
class testy(Screen):
novy_test = ObjectProperty()
class Test(MDApp):
Window.size = (1170 / 3, 2532 / 3)
# input_number = ObjectProperty()
def build(self):
self.theme_cls.material_style = "M3"
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = 'Gray'
return testy()
def get_user_input(self):
print(self.root.ids.my_textfield_1.ids.user.text)
def callback(self, button):
pass
class CustomOverFlowMenu(MDDropdownMenu):
# In this class you can set custom properties for the overflow menu.
pass
Test().run()
test.kv file:
#:import Factory kivy.factory.Factory
#:import CustomOverFlowMenu __main__.CustomOverFlowMenu
<testy>:
name:'testy'
id: testy
MDBoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "MDTopAppBar"
use_overflow: True
overflow_cls: CustomOverFlowMenu()
specific_text_color: .51,.51,.51,1
md_bg_color: 0, 0, 0, 1
left_action_items: [["car", lambda x: Factory.novy_test().open(), '',"Nový test"]]
MDBottomNavigation:
panel_color: "black"
selected_color_background: "white"
text_color_active: "lightgray"
selected_color_background: 1, 1, 1, .4
MDBottomNavigationItem:
name: 'screen 1'
text: 'Testy'
icon: 'road-variant'
MDLabel:
text: 'Test'
halign: 'center'
MDBottomNavigationItem:
name: 'screen 2'
text: 'chyby'
icon: 'alert-circle'
MDLabel:
text: 'Chyby'
halign: 'center'
MDBottomNavigationItem:
name: 'screen 3'
text: 'Settings'
icon: 'cog'
MDLabel:
text: 'LinkedIN'
halign: 'center'
<novy_test#Popup>:
id:my_textfield_1
size_hint: .8, .45
title: 'Nový test'
separator_color: 'black'
title_align: 'center'
BoxLayout:
id: layout
spacing: 10
orientation:'vertical'
MDTextField:
id: user
hint_text: "Číslo testu"
mode: "round"
pos_hint: {"top": 1}
MDFlatButton:
text: 'Štart'
pos_hint: {'center_x': .5}
on_press: app.get_user_input()
MDFlatButton:
pos_hint: {'center_x': .5}
text:'test z nesprávnych'
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
I didn't perfectly understand all that you wanted to do, but in this example, the text a person types into the box will print. I moved the .kv language into a string just for convenience of creating a one-file runnable project. I tested it.
The main point is this code, inside the .kv file/kivy language you can use the id property to get a reference to the objects, and then the .text property of that object is sent as an argument to the function.
on_press: app.get_user_input(user.text)
runnable:
from kivy.core.window import Window
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.menu import MDDropdownMenu
from kivy.uix.popup import Popup
from kivymd.uix.textfield import MDTextField
from kivy.properties import StringProperty
Builder.load_string('''
#:import Factory kivy.factory.Factory
<testy>:
name:'testy'
id: testy
MDBoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "MDTopAppBar"
use_overflow: True
# overflow_cls: CustomOverFlowMenu()
specific_text_color: .51,.51,.51,1
md_bg_color: 0, 0, 0, 1
left_action_items: [["car", lambda x: Factory.NovyTest().open(), '',"Nový test"]]
MDBottomNavigation:
panel_color: "black"
selected_color_background: "white"
text_color_active: "lightgray"
selected_color_background: 1, 1, 1, .4
MDBottomNavigationItem:
name: 'screen 1'
text: 'Testy'
icon: 'road-variant'
MDLabel:
text: 'Test'
halign: 'center'
MDBottomNavigationItem:
name: 'screen 2'
text: 'chyby'
icon: 'alert-circle'
MDLabel:
text: 'Chyby'
halign: 'center'
MDBottomNavigationItem:
name: 'screen 3'
text: 'Settings'
icon: 'cog'
MDLabel:
text: 'LinkedIN'
halign: 'center'
<NovyTest#Popup>:
id:my_textfield_1
size_hint: .8, .45
title: 'Nový test'
separator_color: 'black'
title_align: 'center'
BoxLayout:
id: layout
spacing: 10
orientation:'vertical'
MDTextField:
id: user
hint_text: "Číslo testu"
mode: "round"
pos_hint: {"top": 1}
MDFlatButton:
text: 'Štart'
pos_hint: {'center_x': .5}
# inside .kv/kivy language you can use the id property
on_press: app.get_user_input(user.text)
MDFlatButton:
pos_hint: {'center_x': .5}
text:'test z nesprávnych'
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
MDFlatButton:
text:'test z neurobených'
pos_hint: {'center_x': .5}
'''
)
class NovyTest(Popup):
# just an example, not used in this code
def __init__(self, **kw):
super().__init__(**kw)
class testy(Screen):
# can list objects defined in .kv file and give them a type hint corresponding to object type
novy_test: NovyTest
def __init__(self, **kw):
super().__init__(**kw)
print("creating screen testy")
# novy_test = ObjectProperty()
class Test(MDApp):
Window.size = (1170 / 3, 2532 / 3)
# input_number = ObjectProperty()
def build(self) -> testy:
self.theme_cls.material_style = "M3"
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = 'Gray'
return testy()
def get_user_input(self, input_text, *args):
print(f"{self} user input: {input_text}")
# print(self.root.ids.my_textfield_1.ids.user.text)
def callback(self, button):
pass
class CustomOverFlowMenu(MDDropdownMenu):
# In this class you can set custom properties for the overflow menu.
pass
Test().run()
end
I'm new to Kivy, I'm working on a tracking app for vehicle repair and I've got a list of appointments and I'm trying to go to a different screen when you press an item on the list and I I have no clue on why it isn't working for me as it says that it is on a different screen but it isn't on the app
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivymd.uix.list import ThreeLineAvatarIconListItem
from kivymd.uix.list import ImageLeftWidget
from kivy.uix.screenmanager import Screen, ScreenManager, SwapTransition, CardTransition
from kivy.core.window import Window
import sqlite3
DatabaseConnection = sqlite3.connect('CarWorkshopDB.db')
cursor = DatabaseConnection.cursor()
Window.size= (400, 650)
class MainScreen(Screen):
pass
class AddScreen(Screen):
pass
class DetailsScreen(Screen):
pass
class WorkApp(MDApp):
def build(self):
self.screen_manager = ScreenManager(transition=CardTransition())
self.screen_manager.add_widget(MainScreen(name='MainScreen'))
self.screen_manager.add_widget(AddScreen(name='AddScreen'))
self.screen_manager.add_widget(DetailsScreen(name='DetailsScreen'))
screen = Builder.load_file("test2.kv")
return screen
def on_start(self):
client = 'John smith'
cursor.execute("SELECT TrackingNumber, Plate, Status FROM Appointments WHERE Customer =?", (client,))
for i in cursor:
self.new_message(i[0], i[1], i[2])
def new_message(self, TrackingNumber, Vehicle, Process):
new_message = ThreeLineAvatarIconListItem(text=TrackingNumber, secondary_text=Vehicle, tertiary_text=Process)
new_message.add_widget(ImageLeftWidget(source='RepairIMG.jpg'))
new_message.bind(on_release=self.on_touch_down)
self.root.ids.list.add_widget(new_message)
def on_touch_down(self, x):
print(self.screen_manager.current)
self.screen_manager.current = "DetailsScreen"
self.screen_manager.transition.direction = 'right'
print(self.screen_manager.current)
WorkApp().run()
this is the list code in the kv file
NavigationLayout:
ScreenManager:
id: screen_manager
MainScreen:
name : "MainScreen"
BoxLayout:
orientation:'vertical'
MDBottomNavigation:
panel_color: 1, .643, 0, 1
MDBottomNavigationItem:
name: 'screen 1'
text: 'Home'
icon: 'alpha-h-circle'
MDToolbar:
title: 'Add Repair'
md_bg_color: 1, .643, 0, 1
elevation: 6
pos_hint: {'top':1}
Widget:
MDBottomNavigationItem:
name: 'screen 2'
text: 'Track'
icon: 'alpha-t-circle'
MDToolbar:
id: toolbar
title: 'Track History'
md_bg_color: 1, .643, 0, 1
elevation: 6
pos_hint: {'top':1}
NavigationLayout:
x: toolbar.height
size_hint_y: 1.0 - toolbar.height/root.height
ScreenManager:
Screen:
name: 'ScrollViewScreen'
ScrollView:
MDList:
id: list
MDFloatingActionButton:
icon: 'plus'
md_bg_color: 1, .643, 0, 1
on_release:
screen_manager.current = 'AddScreen'
screen_manager.transition = CardTransition()
screen_manager.transition.direction = "down"
pos_hint: {'x': .84, 'y': .02}
MDBottomNavigationItem:
name: 'screen 4'
text: 'More'
icon: 'dots-horizontal'
MDToolbar:
title: 'More'
md_bg_color: 1, .643, 0, 1
elevation: 6
pos_hint: {'top':1}
Widget:
MDLabel:
text: 'dfsfdsf'
halign: 'center'
AddScreen:
name: 'AddScreen'
id: Add
FloatLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar2
title: 'Add Tracking Number'
md_bg_color: 1, .643, 0, 1
elevation: 6
pos_hint: {'top':1}
MDIconButton:
icon : 'close'
pos_hint : {'top':0.98, 'x':0.85}
on_release :
screen_manager.current = "Main"
screen_manager.transition = CardTransition()
screen_manager.transition.direction = "up"
FloatLayout:
x: toolbar2.height
size_hint_y: 1.0 - toolbar.height/root.height
ScatterLayout:
MDLabel:
text: 'Track Repair'
font_style: 'H4'
valign: 'top'
pos_hint: {'top':1}
text_size: self.size
size_hint: None, None
MDTextFieldRound:
icon_left: 'alpha-t-circle'
hint_text: 'Tracking Number'
normal_color: 1, .643, 0, 1
pos_hint: {'y':.7}
text_size: self.size
MDTextFieldRound:
icon_left: 'alpha-p-circle'
hint_text: 'Postcode'
normal_color: 1, .643, 0, 1
pos_hint: {'y':.6}
text_size: self.size
MDTextButton:
text: "Cant find your tracking number?"
custom_color: 1, .643, 0, 1
pos_hint: {'y':.5}
halign: 'center'
MDRectangleFlatButton:
text: 'confirm'
pos_hint: {'y':.4}
valign: 'middle'
text_size: self.size
DetailsScreen:
name: 'DetailsScreen'
id: Details
BoxLayout:
orientation: 'vertical'
MDLabel:
text: 'details Screen?'
The problem is that in your build() method you are building a widget tree in the lines:
self.screen_manager = ScreenManager(transition=CardTransition())
self.screen_manager.add_widget(MainScreen(name='MainScreen'))
self.screen_manager.add_widget(AddScreen(name='AddScreen'))
self.screen_manager.add_widget(DetailsScreen(name='DetailsScreen'))
But this widget tree is not used in your GUI. The widget tree in your GUI is built from the kv file by:
screen = Builder.load_file("test2.kv")
When your code tries to change the current Screen by using:
self.screen_manager.current = "DetailsScreen"
it is changing the current Screen of a ScreenManager that is not in your GUI.
A fix is to assign the correct value to self.screen_manager, like this:
class WorkApp(MDApp):
def build(self):
screen = Builder.load_file("test2.kv")
self.screen_manager = screen.ids.screen_manager
return screen
I am trying to create a dropdown list that is called when a button is submitted. After the drop down list is called i want the value of the button to be set to the button in the dropdown list that has been selected. I then want to retrieve this value back in my code to carry out some logic. I found this question that has been previously asked and it outlines exactly what i would like to achieve Python, Kivy. Get text from dynamically created buttons with a dropdown. However, i tried incorporating the answer in my code but for some reason the drop down list does not appear. I would really appreciate if someone could help me out and tell me what is it i am doing in correctly.
Scrap.py
from kivy.app import App
from kivy.uix.checkbox import CheckBox
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.uix.dropdown import DropDown
import datetime as dt
Window.size = (800,600)
class CustomDropDown(DropDown):
def __init__(self, **kwargs):
super(CustomDropDown, self).__init__(**kwargs)
self.add_buttons()
def add_buttons(self):
for index in range(10):
btn = Button(text='Value %d' % index, size_hint_y=None, height=44)
btn.bind(on_release=lambda btn: self.select(btn.text))
self.add_widget(btn)
class MainWindow(Screen):
check_solid = ObjectProperty(False)
check_water = ObjectProperty(False)
check_boiling = ObjectProperty(False)
s_id = str(dt.datetime.now().strftime("%y%m%d%H%M"))
def btn(self):
print(self.check_solid.state)
print(self.check_water.state)
print(self.check_boiling.state)
class MyScreenManager(ScreenManager):
def Run_Draws_Test(self, value):
print(value)
class Checkbox(CheckBox):
pass
class ScrapApp(App):
title = "Chemistry Sample Requests"
def build(self):
return MyScreenManager()
if __name__ == '__main__':
ScrapApp().run()
scrap.kv
#:import Factory kivy.factory.Factory
<Button>:
size_hint: 0.1,0.1
<Label>:
size_hint: 0.1,0.1
<Checkbox>:
size_hint: 0.1,0.1
<TextInput>:
size_hint: 0.2,0.1
multiline: False
<CustomDropDown>:
on_select:
app.root.ids.MainWindow.ids.mainbutton.text = '{}'.format(args[1])
app.root.Run_Draws_Test(args[1])
<MainWindow>:
orientation: "vertical"
check_solid: solid_check
check_boiling: boiling_check
check_water: water_check
FloatLayout:
Label:
text: "Sample ID: "
pos_hint: {"x":0.05, "top":0.95}
Label:
text: root.s_id
pos_hint: {"x":0.2, "top": 0.95}
Label:
text: "Plant ID: "
pos_hint: {"x":0.05, "top": 0.8}
Button:
id: mainbutton
text: "Choose"
pos: 400,400
size_hint: None,None
size: 150, 50
on_release: Factory.CustomDropDown().open(self)
Label:
text: "Formulation: "
pos_hint: {"x":0.05, "top": 0.65}
TextInput:
id: id_formulation
pos_hint: {"x":0.2, "top": 0.65}
Label:
text: "Solids Test: "
pos_hint: {"x":0.05, "top": 0.5}
Checkbox:
id: solid_check
pos_hint: {"x":0.25, "top": 0.5}
Label:
text: "Water Content Test: "
pos_hint: {"x":0.05, "top": 0.35}
Checkbox:
id: water_check
pos_hint: {"x":0.25, "top": 0.35}
Label:
text: "Boiling Point: "
pos_hint: {"x":0.05, "top": 0.2}
Checkbox:
id: boiling_check
pos_hint: {"x":0.25, "top": 0.2}
Button:
text: "Submit"
pos_hint: {"x": 0.7, "top": 0.5}
on_release: root.btn()
<MyScreenManager>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 0.5
Rectangle:
pos: 0,0
size: 800, 600
MainWindow:
id: MainWindow
name: 'MainWindow'
I've run into bugs like this before. I don't know if Kivy is working as intended with this or how to fix it. Anyone with more knowledge than me, I'd be glad to hear the reasoning to this.
class CustomDropDown(DropDown):
def __init__(self, **kwargs):
super(CustomDropDown, self).__init__(**kwargs)
self.add_buttons()
def add_buttons(self):
for index in range(10):
#btn = Button(text='Value %d' % index, size_hint_y=None, height=44)
btn = Button(text='Value %d' % index)
btn.size_hint_y = None
btn.height = 44
btn.bind(on_release=lambda btn: self.select(btn.text))
self.add_widget(btn)
These kind of things cause me nothing but frustration.
I have problems with giving the text of my button when clicking on the label in list from MDDropdownMenu. In my testing main.py and main.kv it has been working, but when it was implemented in main code - it has an error AttributeError: 'super' object has no attribute '__getattr__'
There is my main.py:
# encoding=utf8
import sys
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.core.text import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.screenmanager import SlideTransition
from kivy.properties import ObjectProperty, NumericProperty, StringProperty, BooleanProperty, ListProperty
from kivy.utils import get_hex_from_color
from kivy.metrics import dp, sp, pt
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
from kivymd.theming import ThemeManager
from kivymd.dialog import MDDialog
from kivymd.label import MDLabel
from kivymd.button import MDRoundFlatButton
from kivymd.button import MDRaisedButton
from kivymd.list import ILeftBodyTouch
from kivymd.popupscreen import MDPopupScreen
from newpickers import MDDatePicker
from kivymd.menus import MDDropdownMenu
year1 = 0
monthlist = ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь',]
monthnum = 0
selected_date = ''
class Manager(ScreenManager):
def __init__(self, **kwargs):
super(Manager, self).__init__(**kwargs)
class MainMenu(Screen):
pass
class InfoMenu(Screen):
pass
class ListButton(MDRaisedButton):
pass
class DateSetupMenu(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.menu_items = [
{
"viewclass": "MDMenuItem",
"text": "%d" % i,
"callback": self.callbackforlist,
}
for i in range(1900, 2100)
]
def callbackforlist(self, *args):
pass
class Year_layout_popup1(GridLayout):
pass
class Year_layout_scrollview1(ScrollView):
pass
class YearButton1(MDRaisedButton):
pass
class YearSelectionButton(MDRoundFlatButton):
def on_release(self):
global year1
year1 = int(self.text)
class DatePickPopup(Popup):
pass
class Month_layout_popup(GridLayout):
pass
class Month_layout_scrollview(ScrollView):
pass
class MonthButton(MDRaisedButton):
pass
class DatePickerWidget(MDDatePicker):
pass
class MonthSelectionButton(MDRoundFlatButton):
def on_release(self):
global monthlist
global monthnum
monthnum = int(monthlist.index(str(self.text)))
monthnum += 1
class MonthPickPopup(Popup):
pass
class yearselectbtn(Button):
pass
class monthselectbtn(Button):
pass
class rt_android(App):
theme_cls = ThemeManager()
theme_cls.device_orientation == 'portrait'
title = 'Rectif Tattva Android Edition'
yearselectlabeltext = StringProperty('Выберите год рождения')
monthselectlabeltext = StringProperty('Выберите месяц рождения')
dateselectlabeltext = StringProperty('Выберите день рождения')
mlist = ['Месяц','Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь']
VARIABLE = ""
def build(self):
self.theme_cls.theme_style = 'Light'
Window.size = (480, 854)
return Manager()
def CloseExitPopup(self, *args):
from kivymd.toast.kivytoast import toast
if args[0] == 'Да':
App.get_running_app().stop()
else:
pass
def ExitDialog(self):
self.dialog = MDDialog(
title='Выход из приложения', size_hint=(.8, .25), text_button_ok='Нет',
text="Вы точно хотите выйти?",
text_button_cancel='Да',
events_callback=self.CloseExitPopup)
self.dialog.open()
def OpenDatePicker(self, *args):
DatePickerWidget(self.set_date, year1, monthnum, 1).open()
def set_date(self, date_obj):
global selected_date
global year1
global monthnum
global daynum
self.setupdate = date_obj
selected_date = str(self.setupdate)
year1 = int(selected_date[0:4])
monthnum = int(selected_date[5:7])
daynum = int(selected_date[8:10])
month_id = monthnum-1
def year_select_clicked1(self):
self.ylp = Year_layout_popup1()
self.ylp.bind(minimum_height=self.ylp.setter('height'))
# for i in range(1950, 2019):
# self.ysb = YearSelectionButton()
# self.ysb.text = str(i)
# self.ylp.add_widget(self.ysb)
for i in range(1950, 2019):
self.ysb = yearselectbtn()
self.ysb.text = str(i)
self.ylp.add_widget(self.ysb)
root = Year_layout_scrollview1()
root.add_widget(self.ylp)
self.popup = DatePickPopup()
self.popup.content = root
self.popup.open()
def month_select_clicked(self):
global monthlist
self.mlp = Month_layout_popup()
self.mlp.bind(minimum_height=self.mlp.setter('height'))
# for i in range(0, 12):
# self.msb = MonthSelectionButton()
# self.msb.text = str(monthlist[i])
# self.msb.id = str(i)
# self.mlp.add_widget(self.msb)
for i in range(0, 12):
self.msb = monthselectbtn()
self.msb.text = str(monthlist[i])
self.msb.id = str(i)
self.mlp.add_widget(self.msb)
root = Month_layout_scrollview()
root.add_widget(self.mlp)
self.popup_m = DatePickPopup()
self.popup_m.content = root
self.popup_m.open()
def closeitpls(self):
self.popup.dismiss()
def closeitpls_m(self):
self.popup_m.dismiss()
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
class CreditsImage(Image):
pass
with open("main_interface.kv", encoding='utf8') as f:
main_interface = Builder.load_string(f.read())
if __name__ == '__main__':
rt_android().run()
And there is my main_interface.kv:
# encoding=utf8
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Factory kivy.factory.Factory
#:import MDLabel kivymd.label.MDLabel
#:import MDRaisedButton kivymd.button.MDRaisedButton
#:import MDRectangleFlatButton kivymd.button.MDRectangleFlatButton
#:import MDToolbar kivymd.toolbar.MDToolbar
#:import MDRoundFlatButton kivymd.button.MDRoundFlatButton
#:import MDDropdownMenu kivymd.menus.MDDropdownMenu
#:import MDMenuItem kivymd.menus.MDMenuItem
#:import hex kivy.utils.get_color_from_hex
#:set white hex('#00a86b')
<MenuButton#MDRaisedButton>:
font_size: dp(8)
elevation_normal: 3
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint_x: 0.5
height: dp(50)
<InfoMenuButton#MDRaisedButton>:
font_size: dp(8)
elevation_normal: 3
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
height: dp(50)
<DateSetupMenuButton#MDRaisedButton>:
font_size: dp(8)
elevation_normal: 3
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
height: dp(50)
<Year_layout_popup1>:
cols: 1
spacing: 15
padding: [10,10,10,10]
size_hint_y: None
<Year_layout_scrollview1>:
size_hint: (1, None)
size: Window.width*0.8, Window.height*0.7
<YearButton1>:
font_size: dp(8)
elevation_normal: 3
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
height: dp(50)
<DatePickPopup>:
title: 'Выбор года рождения'
size_hint: 0.8, 0.8
auto_dismiss: False
separator_color: white
title_color: white
background: 'assets/whiteback.png'
<YearSelectionButton>:
font_size: dp(8)
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 1, None
height: dp(50)
on_press:
app.yearselectlabeltext = self.text
on_release:
app.closeitpls()
<Month_layout_popup>:
cols: 1
spacing: 15
padding: [10,10,10,10]
size_hint_y: None
<Month_layout_scrollview>:
size_hint: (1, None)
size: Window.width*0.8, Window.height*0.7
<MonthButton>:
font_size: dp(8)
elevation_normal: 3
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
height: dp(50)
<MonthPickPopup>:
title: 'Выбор месяца рождения'
size_hint: 0.8, 0.8
auto_dismiss: False
separator_color: white
title_color: white
background: 'assets/whiteback.png'
<MonthSelectionButton>:
id: ''
font_size: dp(8)
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 1, None
height: dp(50)
on_press:
app.monthselectlabeltext = self.text
on_release:
app.closeitpls_m()
<yearselectbtn>:
font_size: dp(16)
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 1, None
height: dp(50)
background_color: (255, 255, 255, 1)
color: (0,0,0,1)
on_press:
app.yearselectlabeltext = self.text
on_release:
app.closeitpls()
<monthselectbtn>:
font_size: dp(16)
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 1, None
height: dp(50)
background_color: (255, 255, 255, 1)
color: (0,0,0,1)
on_press:
app.monthselectlabeltext = self.text
on_release:
app.closeitpls_m()
<MDMenuItem>:
on_release:
app.root.ids.buttonoflist.text = self.text
<ListButton>:
id: buttonoflist
font_size: dp(8)
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
height: dp(50)
<Manager>:
MainMenu:
name: 'main_menu'
InfoMenu:
name: 'info_menu'
DateSetupMenu:
name: 'date_setup_menu'
<MainMenu>:
AnchorLayout:
anchor_y: 'top'
MDToolbar:
title: app.title
elevation: 10
md_bg_color: white
AnchorLayout:
anchor_y: 'bottom'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.25
spacing: dp(10)
padding: [0, 0, 0, dp(10)]
MenuButton:
text: 'Приступить'
on_press:
app.root.transition = SlideTransition(direction='left', duration = .17)
on_release:
root.manager.current = 'date_setup_menu'
MenuButton:
text: 'Инфо'
on_press:
app.root.transition = SlideTransition(direction='left', duration = .17)
on_release:
root.manager.current = 'info_menu'
MenuButton:
text: 'Выход'
on_release:
app.ExitDialog()
<InfoMenu>:
AnchorLayout:
anchor_y: 'top'
MDToolbar:
title: 'Инфо'
elevation: 10
md_bg_color: white
BoxLayout:
size_hint_y: 0.4
orientation: 'vertical'
spacing: 5
padding: [0, dp(90), 0, 0]
pos_hint: {'center_x': .5, 'center_y': 1}
CreditsImage:
source: 'assets/info_credits_table.png'
size_hint_y: 0.8
MDLabel:
text: 'версия программы: 1.0.0'
font_name: 'assets/Ponter.ttf'
color: (255,255,255,1)
size_hint_y: 0.2
font_size: dp(20)
halign: 'center'
valign: 'top'
text_size: self.size
AnchorLayout:
anchor_y: 'bottom'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.25
padding: [0, 0, 0, dp(15)]
InfoMenuButton:
text: 'Назад'
on_press:
app.root.transition = SlideTransition(direction='right', duration = .17)
on_release:
root.manager.current = 'main_menu'
<DateSetupMenu>:
AnchorLayout:
anchor_y: 'top'
MDToolbar:
title: 'Выбор параметров'
elevation: 10
md_bg_color: white
AnchorLayout:
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.25
padding: [0, dp(15), 0, 0]
spacing: dp(5)
ListButton:
id: buttonoflist
text: 'Выбор'
on_release:
MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
YearButton1:
text: app.yearselectlabeltext
on_release:
app.year_select_clicked1()
MonthButton:
text: app.monthselectlabeltext
on_release:
app.month_select_clicked()
DateSetupMenuButton:
text: app.dateselectlabeltext
on_release:
app.OpenDatePicker()
AnchorLayout:
anchor_y: 'bottom'
BoxLayout:
orientation: 'vertical'
size_hint: 0.95, 0.25
padding: [0, 0, 0, dp(15)]
DateSetupMenuButton:
text: 'Назад'
on_press:
app.root.transition = SlideTransition(direction='right', duration = .17)
on_release:
root.manager.current = 'main_menu'
I need to change the text of «ListButton» object after clicking MDMenuItem proreply. I dont know, why it is working in standalone code, but in my main code it has that horrible problem...
Errors - KeyError & AttributeError
Traceback (most recent call last):
File "kivy/properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
KeyError: 'buttonoflist'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
File ".../main.kv", line 132, in <module>
app.root.ids.buttonoflist.text = self.text
File "kivy/properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
Root Cause
The first error encountered was KeyError because the id, 'buttonoflist' does not exist in Kivy self.ids dictionary type property.
The second error encountered was AttributeError because the id, 'buttonoflist' does not exist in the root (which is a ScreenManager).
Solution
Since id: buttonoflist is declared in the Screen,
DateSetupMenu:, you have to add an id to DateSetupMenu object so
that you can access / reference it.
Replace app.root.ids.buttonoflist.text with app.root.ids.date_setup_menu.ids.buttonoflist.text
Snippets - kv file
<MDMenuItem>:
on_release:
app.root.ids.date_setup_menu.ids.buttonoflist.text = self.text
...
<Manager>:
...
DateSetupMenu:
id: date_setup_menu
name: 'date_setup_menu'
...
Output
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am writing a chat app using kivy and socket. However, whenever my app receives a message, I will always get an AttributeError: 'super' object has no attribute '__getattr__'.
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivymd.dialog import MDDialog
from kivymd.theming import ThemeManager
from kivymd.navigationdrawer import NavigationLayout
from kivymd.list import OneLineAvatarListItem, ILeftBody
from kivymd.toast import toast
from kivymd.dialog import MDDialog
from kivy.uix.popup import Popup
from threading import Thread
import socket
sock = socket.socket()
sock.connect(('127.0.0.1', 6718))
sock.sendall(b"add_contact hello llo")
sock = socket.socket()
sock.connect(('127.0.0.1', 6718))
sock.sendall(b'new llo')
class MyLayout(BoxLayout):
scr_mngr = ObjectProperty(None)
def check_data_login(self):
username = self.scr_mngr.screen1.username.text
password = self.scr_mngr.screen1.password.text
print(username)
print(password)
if username == "KivyMD" and password == "kivy":
self.ids["wrongpass"].text = ""
self.change_screen("screen2")
else:
self.ids["wrongpass"].text = "Wrong username or password, please try again"
def change_screen(self, screen, *args):
self.scr_mngr.transition.direction = 'left'
self.scr_mngr.current = screen
def back_to_chat(self):
self.scr_mngr.transition.direction = 'right'
self.scr_mngr.current = 'screen2'
class nav_layout(NavigationLayout):
def print_text(self):
print('hello')
def check_data_login(self):
username = self.ids.screen1.username.text
password = self.ids.screen1.password.text
print(username)
print(password)
if username == "KivyMD" and password == "kivy":
self.change_screen("screen2")
self.ids.wrongpass.text = ""
else:
self.ids.wrongpass.text = \
"Wrong username or password, please try again"
def change_screen(self, screen, *args):
self.ids.scr_mngr.transition.direction = 'left'
self.ids.scr_mngr.current = screen
def back_to_chat(self):
self.ids.scr_mngr.transition.direction = 'right'
self.ids.scr_mngr.current = 'screen2'
def logout(self):
# logout function, returns to screen 1
self.ids.scr_mngr.current = 'screen1'
def oof(self, data):
self.ids.Chat_String.text = data
class UploadPopup(Popup):
def load(self, path, selection):
print(path, selection)
KV = """
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
#:import MDTextField kivymd.textfields.MDTextField
#:import MDSeparator kivymd.card.MDSeparator
#:import MDThemePicker kivymd.theme_picker.MDThemePicker
#:import CardTransition kivy.uix.screenmanager.CardTransition
#:import Factory kivy.factory.Factory
<MDCustomIconItem>:
text: root.text
AvatarSampleWidget:
source: root.icon
<UploadPopup>:
id: popup
title: "Upload"
BoxLayout:
FileChooserIconView:
id: FileChoose
pos_hint_x: 0.5
pos_hint_y: 0.5
on_selection: root.load(FileChoose.path, FileChoose.selection)
MDRaisedButton:
text: "Upload"
text_color: (0,0,0,1)
on_release: root.load(FileChoose.path, FileChoose.selection)
on_release: popup.dismiss()
MDRaisedButton:
text: "Close"
text_color: (0,0,0,1)
on_release: popup.dismiss()
nav_layout:
id: nav_layout
MDNavigationDrawer:
id: nav_drawer
drawer_logo: 'logo.png'
NavigationDrawerToolbar:
title: 'hello'
NavigationDrawerIconButton:
icon: 'settings'
text: 'Account Settings'
on_release: root.change_screen('screen3')
NavigationDrawerIconButton:
icon: 'face'
text: 'Friends'
on_release: root.print_text()
NavigationDrawerIconButton:
icon: 'logout'
text: 'Logout'
on_release: root.logout()
NavigationDrawerDivider:
height: dp(1)
MyLayout:
scr_mngr: scr_mngr
orientation: 'vertical'
ScreenManager:
transition: CardTransition()
id: scr_mngr
screen1: screen1
Screen:
id: screen1
name: 'screen1'
username: username
password: password
BoxLayout:
size_hint: None, None
size: dp(520), dp(340)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
BoxLayout:
orientation:'vertical'
padding: dp(20)
spacing:20
MDLabel:
text: 'Chat App'
theme_text_color: 'Secondary'
font_style:"Title"
size_hint_y: None
height: dp(36)
MDSeparator:
height: dp(1)
MDTextField:
id: username
hint_text: "Username "
size_hint_y: 0.9
helper_text_mode: "on_focus"
MDTextField:
id: password
hint_text: "Password "
helper_text_mode: "on_focus"
size_hint_y: 0.9
password: True
MDFlatButton:
text: "Login"
pos_hint: {'center_x': 0.5}
on_release: root.check_data_login()
MDLabel:
id: wrongpass
color: 1,0,1,1
text: ""
Screen:
name: 'screen2'
id: screen2
Toolbar:
id: toolbar
title: "Welcome ! "
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
MDLabel:
font_style: 'Title'
theme_text_color: 'Primary'
text: "Data :"
height: self.texture_size[1] + dp(3)
halign: 'center'
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
Screen:
name: 'screen3'
id: 'screen3'
Toolbar:
id: tools
title: "Your Profile"
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['arrow-left', lambda x: root.back_to_chat()]]
MDLabel:
id: 'Profile_String'
font_size: 90
text: "XXX"
halign: 'center'
pos_hint: {'center_x': 0.5, 'center_y': 0.85}
Screen:
name: 'screen4'
id: 'screen4'
Toolbar:
id: tools
title: "XXX"
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
ScrollView:
pos_hint: {'center_x': .55, 'y': .35}
MDLabel:
id: 'Chat_String'
font_size: 40
text: "XXX"
MDTextField:
id: 'Input_String'
hint_text: 'Enter Your Message...'
helper_text_mode: 'on_focus'
pos_hint: {'center_x': 0.35, 'center_y': 0.2}
size_hint_x: 0.6
multiline: True
MDRaisedButton:
id: 'Send_Button'
text: 'Send'
pos_hint: {'center_x': 0.75, 'center_y': 0.2}
MDRaisedButton:
id: 'Choose_Image'
text: 'Attach File'
pos_hint: {'center_x': 0.9, 'center_y': 0.2}
on_release: Factory.UploadPopup().open()
"""
class MDCustomIconItem(OneLineAvatarListItem):
icon = StringProperty('')
text = StringProperty()
def _set_active(self, active, list):
pass
class AvatarSampleWidget(ILeftBody, Image):
pass
class MyApp(App):
theme_cls = ThemeManager()
theme_cls.primary_palette = 'Blue'
title = "Navigation Drawer"
main_widget = None
def __getattr__(self, attr):
return super().__getattr__(attr)
def build(self):
self.main_widget = Builder.load_string(KV)
return self.main_widget
def callback(self, instance, value):
self.main_widget.ids.scr_mngr.current = 'screen4'
def recover_data(self):
print('started')
while True:
data = sock.recv(1024)
data = data.decode()
if data:
print(data)
data = data.split()
data = data[-1] + ": " + ' '.join(data[:-1])
r = data + '\n'
open('chat1.txt', 'a+').write(r)
e = open('chat1.txt', 'r').readlines()
nav_layout().oof('\n\r'.join(e))
print(data)
def on_start(self):
Thread(target=self.recover_data).start()
for i in range(15):
self.main_widget.ids.nav_drawer.add_widget(
MDCustomIconItem(
text="Item menu %d" % i,
icon='logo.png',
on_release=lambda x, y=i: self.callback(x, y)))
MyApp().run()
I know this question has been asked before multiple times on StackOverflow, but none of them solved my problem.
Any help will be appreciated, Thank You!
**Edit: ** My full error message is here
Exception has occurred: AttributeError
'super' object has no attribute '__getattr__'
File "/Users/grace/Desktop/Android_APP/kivy/properties.pyx", line 841, in kivy.properties.ObservableDict.__getattr__
File "/Users/grace/Desktop/Android_APP/app.py", line 81, in oof
self.ids.Chat_String.text = data
File "/Users/grace/Desktop/Android_APP/app.py", line 334, in recover_data
nav_layout().oof('\n\r'.join(e))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 869, in run
del self._target, self._args, self._kwargs
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 885, in _bootstrap
self._bootstrap_inner()
Reason
The error was due to assigning string value to id in kv file.
Solution
Remove single quote from all id in kv file.
Kv Language » Referencing Widgets
When assigning a value to id, remember that the value isn’t a string.
There are no quotes: good -> id: value, bad -> id: 'value'
Example
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivymd.dialog import MDDialog
from kivymd.theming import ThemeManager
from kivymd.navigationdrawer import NavigationLayout
from kivymd.list import OneLineAvatarListItem, ILeftBody
# from kivymd.toast import toast
from kivymd.dialog import MDDialog
from kivy.uix.popup import Popup
from threading import Thread
import socket
# sock = socket.socket()
# sock.connect(('127.0.0.1', 6718))
# sock.sendall(b"add_contact hello llo")
#
# sock = socket.socket()
# sock.connect(('127.0.0.1', 6718))
#
# sock.sendall(b'new llo')
class MyLayout(BoxLayout):
scr_mngr = ObjectProperty(None)
def check_data_login(self):
username = self.scr_mngr.screen1.username.text
password = self.scr_mngr.screen1.password.text
print(username)
print(password)
if username == "KivyMD" and password == "kivy":
self.ids["wrongpass"].text = ""
self.change_screen("screen2")
else:
self.ids["wrongpass"].text = "Wrong username or password, please try again"
def change_screen(self, screen, *args):
self.scr_mngr.transition.direction = 'left'
self.scr_mngr.current = screen
def back_to_chat(self):
self.scr_mngr.transition.direction = 'right'
self.scr_mngr.current = 'screen2'
class nav_layout(NavigationLayout):
def print_text(self):
print('hello')
print("self.ids.Chat_String.text=", self.ids.Chat_String.text)
def check_data_login(self):
username = self.ids.screen1.username.text
password = self.ids.screen1.password.text
print(username)
print(password)
if username == "KivyMD" and password == "kivy":
self.change_screen("screen2")
self.ids.wrongpass.text = ""
else:
self.ids.wrongpass.text = \
"Wrong username or password, please try again"
def change_screen(self, screen, *args):
self.ids.scr_mngr.transition.direction = 'left'
self.ids.scr_mngr.current = screen
def back_to_chat(self):
self.ids.scr_mngr.transition.direction = 'right'
self.ids.scr_mngr.current = 'screen2'
def logout(self):
# logout function, returns to screen 1
self.ids.scr_mngr.current = 'screen1'
def oof(self, data):
self.ids.Chat_String.text = data
class UploadPopup(Popup):
def load(self, path, selection):
print(path, selection)
KV = """
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
#:import MDTextField kivymd.textfields.MDTextField
#:import MDSeparator kivymd.card.MDSeparator
#:import MDThemePicker kivymd.theme_picker.MDThemePicker
#:import CardTransition kivy.uix.screenmanager.CardTransition
#:import Factory kivy.factory.Factory
<MDCustomIconItem>:
text: root.text
AvatarSampleWidget:
source: root.icon
<UploadPopup>:
id: popup
title: "Upload"
BoxLayout:
FileChooserIconView:
id: FileChoose
pos_hint_x: 0.5
pos_hint_y: 0.5
on_selection: root.load(FileChoose.path, FileChoose.selection)
MDRaisedButton:
text: "Upload"
text_color: (0,0,0,1)
on_release: root.load(FileChoose.path, FileChoose.selection)
on_release: popup.dismiss()
MDRaisedButton:
text: "Close"
text_color: (0,0,0,1)
on_release: popup.dismiss()
nav_layout:
id: nav_layout
MDNavigationDrawer:
id: nav_drawer
drawer_logo: 'logo.png'
NavigationDrawerToolbar:
title: 'hello'
NavigationDrawerIconButton:
icon: 'settings'
text: 'Account Settings'
on_release: root.change_screen('screen3')
NavigationDrawerIconButton:
icon: 'face'
text: 'Friends'
on_release: root.print_text()
NavigationDrawerIconButton:
icon: 'logout'
text: 'Logout'
on_release: root.logout()
NavigationDrawerDivider:
height: dp(1)
MyLayout:
scr_mngr: scr_mngr
orientation: 'vertical'
ScreenManager:
transition: CardTransition()
id: scr_mngr
screen1: screen1
Screen:
id: screen1
name: 'screen1'
username: username
password: password
BoxLayout:
size_hint: None, None
size: dp(520), dp(340)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
BoxLayout:
orientation:'vertical'
padding: dp(20)
spacing:20
MDLabel:
text: 'Chat App'
theme_text_color: 'Secondary'
font_style:"Title"
size_hint_y: None
height: dp(36)
MDSeparator:
height: dp(1)
MDTextField:
id: username
hint_text: "Username "
size_hint_y: 0.9
helper_text_mode: "on_focus"
MDTextField:
id: password
hint_text: "Password "
helper_text_mode: "on_focus"
size_hint_y: 0.9
password: True
MDFlatButton:
text: "Login"
pos_hint: {'center_x': 0.5}
on_release: root.check_data_login()
MDLabel:
id: wrongpass
color: 1,0,1,1
text: ""
Screen:
name: 'screen2'
id: screen2
Toolbar:
id: toolbar
title: "Welcome ! "
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
MDLabel:
font_style: 'Title'
theme_text_color: 'Primary'
text: "Data :"
height: self.texture_size[1] + dp(3)
halign: 'center'
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
Screen:
name: 'screen3'
id: screen3
Toolbar:
id: tools
title: "Your Profile"
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['arrow-left', lambda x: root.back_to_chat()]]
MDLabel:
id: Profile_String
font_size: 90
text: "XXX"
halign: 'center'
pos_hint: {'center_x': 0.5, 'center_y': 0.85}
Screen:
name: 'screen4'
id: screen4
Toolbar:
id: tools
title: "XXX"
pos_hint: {'center_x': 0.5, 'center_y': 0.96}
md_bg_color: app.theme_cls.primary_color
background_palette: 'DeepPurple'
background_hue: 'A400'
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
ScrollView:
id: sv
pos_hint: {'center_x': .55, 'y': .35}
MDLabel:
id: Chat_String
font_size: 40
text: "XXX"
MDTextField:
id: Input_String
hint_text: 'Enter Your Message...'
helper_text_mode: 'on_focus'
pos_hint: {'center_x': 0.35, 'center_y': 0.2}
size_hint_x: 0.6
multiline: True
MDRaisedButton:
id: Send_Button
text: 'Send'
pos_hint: {'center_x': 0.75, 'center_y': 0.2}
MDRaisedButton:
id: Choose_Image
text: 'Attach File'
pos_hint: {'center_x': 0.9, 'center_y': 0.2}
on_release: Factory.UploadPopup().open()
"""
class MDCustomIconItem(OneLineAvatarListItem):
icon = StringProperty('')
text = StringProperty()
def _set_active(self, active, list):
pass
class AvatarSampleWidget(ILeftBody, Image):
pass
class MyApp(App):
theme_cls = ThemeManager()
theme_cls.primary_palette = 'Blue'
title = "Navigation Drawer"
main_widget = None
def __getattr__(self, attr):
return super().__getattr__(attr)
def build(self):
self.main_widget = Builder.load_string(KV)
return self.main_widget
def callback(self, instance, value):
self.main_widget.ids.scr_mngr.current = 'screen4'
def recover_data(self):
print('started')
while True:
data = sock.recv(1024)
data = data.decode()
if data:
print(data)
data = data.split()
data = data[-1] + ": " + ' '.join(data[:-1])
r = data + '\n'
open('chat1.txt', 'a+').write(r)
e = open('chat1.txt', 'r').readlines()
nav_layout().oof('\n\r'.join(e))
print(data)
def on_start(self):
Thread(target=self.recover_data).start()
for i in range(15):
self.main_widget.ids.nav_drawer.add_widget(
MDCustomIconItem(
text="Item menu %d" % i,
icon='logo.png',
on_release=lambda x, y=i: self.callback(x, y)))
MyApp().run()
Output