I have a trained model which is loading in the main python file. It is working and giving predictions when I choose kivy's FileChooseListView but I wanted to make it better so I used plyer filechooser which did load images but the problem is now my model is not loading. Its not giving any error either. Can anyone tell what the problem is?
I have tried correcting it and debugging but nothing is happening.
main.py
class UploadScreen(Screen):
def file_chooser(self):
filechooser.open_file(on_selection=self.selected)
def selected(self, filename):
try:
self.ids.my_image.source = filename[0]
print(filename[0])
CATEGORIES = ['Diving Side', # 1.
'Golf-Swing-Front', # 2.
'Golf-Swing-Side', # 3.
'Kicking-Front', # 4.
'Kicking-Side', # 5.
'Lifting', # 6
'Riding-Horse', # 7
'Run-Side', # 8.
'SkateBoarding-Front', # 9
'Swing-Bench', # 10.
'Swing-SideAngle', # 11
'Walk-Front' # 12.
]
model = tf.keras.models.load_model("./model/model") /// Model is not loading
size = (90, 90)
img_array = cv2.imread(filename[0])
pd_array = []
im = cv2.resize(img_array, size, cv2.INTER_AREA)
im = im.astype('float32')
pd_array.append(im)
np_image = np.array(pd_array)
print("NP array ")
print(np_image.shape)
predictions = model.predict(np_image)
top = np.argmax(predictions)
print(predictions)
# top=top-1
print(top)
print("prediction is "+CATEGORIES[top])
results = CATEGORIES[top]
print(results)
name = results
# Update the label
self.ids.name_label.text = name
print("Captured")
except:
pass
.kv
<UploadScreen>:
name: 'upload'
id: upload
orientation: 'vertical'
canvas:
Color:
# rgba: 0.439,0.501,0.564,1
rgb: 0.662, 0.662, 0.662, 1
Rectangle:
size: self.size
pos: self.pos
MDGridLayout:
rows:5
cols:1
spacing: 25
padding: 25
MDLabel:
id: name_label
text: "Results"
bold: True
font_size: 35
color: 0.137, 0.156, 0.419, 1
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
MDRaisedButton:
text: 'Select Image'
font_size: 18
size_hint: None, None
width: root.width*1
height: root.height*0.1
md_bg_color: 0.258, 0.372, 0.921, 1
text_color: 1,1,1,1
pos_hint: {'center_x':0.5,'center_y':0.3}
on_press: root.file_chooser()
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 50
spacing: 20
Image:
id: my_image
source: ""
MDRaisedButton:
text: 'Back'
font_size: 18
size_hint: None, None
width: root.width*1
height: root.height*0.1
md_bg_color: 0.258, 0.372, 0.921, 1
text_color: 1,1,1,1
pos_hint: {'center_x':0.5,'center_y':0.3}
on_press: root.manager.current = 'main'
Related
I have a specific Boxlayout that contains labels to show values in a row; now there are several rows and each is in a boxlayout. I was wondering if I could make a class of the boxlayout including all the labels. So when I go to my .kv file I just call the class and don't have to repeat all the params.
EDIT: IHAVE PLACED THE CORRESPONDING .KV
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
title: "My Stock Tickers"
left_action_items: [["menu", lambda x: x]]
type: 'top'
MyBox:
size_hint: None, None
size: 400, 100
pos_hint: {"center_x": 0.5}
#elevation: 20
padding: 25
spacing: 25
md_bg_color: [0, .7, 1, 1]
#Widget:
#size_hint_y : None
#height: 10
MDLabel:
text: "Enter Ticker"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
MDTextFieldRound:
#id: user
width: 30
font_size: 18
#padding_y: 15
spacing: '20dp'
MDFIconButton:
user_font_size: "15sp"
icon: "plus"
opposite_colors: True
elevation: 8
md_bg_color: 1, 0, 0, 1
spacing: '20dp'
MDLabel:
id: t_price
text: "000.00"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
padding_y: 10
MDLabel:
id: t_change
text: "00.00"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
padding_y: 10
MyBox:
size_hint: None, None
size: 400, 200
md_bg_color: [0, .9, 1, 1]
#spacing: 10
orientation: "vertical"
pos_hint: {"center_x": 0.5}
MyBox: # Title Row
size_hint: 1, None
height: 30
Widget:
size_hint_x : None
width: 20
MDLabel:
#color: 72/255,89/255,89/255,1
color: 0,0,0,1
text: "NAME"
halign: 'left'
size_hint: None, 1
width: 100
MDLabel:
color: (0,0,0,1)
text: "Value"
MDLabel:
color: (0,0,0,1)
text: "Change"
MDLabel:
color: (0,0,0,1)
text: "Chg %"
MyRowBox: #1st Row
id: row1
#self.name.text: "Dow" ????????
#self.value.text: "000.000" ????????
#self.change.text: "000.000" ????????
#self.percnt.text: "0.01%" ????????
My example of what i thought would work would be something like this (in python): EDIT: I PLACED A WORKING SAMPLE
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.behaviors import RectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel
from kivymd.uix.textfield import MDTextField
from kivymd.uix.button import MDIconButton
from kivymd.uix.widget import MDWidget
class MDFIconButton(MDIconButton):
pass
class MyBox(MDBoxLayout):
class update():
pass
class MyRowBox(MDBoxLayout):
def __init__(self, **kwargs):
super(MyRowBox, self).__init__(**kwargs)
size_hint= 1, None
height= 30
self.add_widget(MDWidget(size_hint_x= None, width= 20))
self.name = (MDLabel( color= [72 / 255, 89 / 255, 89 / 255, 1],halign= 'left', size_hint=[None, 1],width= 100))
self.add_widget(self.name)
self.value = MDLabel(halign= 'left')
self.add_widget(self.value)
self.change = MDLabel(halign='left')
self.add_widget(self.change)
self.percnt = MDLabel(halign='left')
self.add_widget(self.percnt)
self.name.text = "Dow"
self.value.text = "000.000"
self.change.text = "000.000"
self.percnt.text = "000.000"
self.change.font_size = 12
self.percnt.font_size = 12
self.name.color = [72 / 255, 89 / 255, 89 / 255, 1]
self.value.color = [0, 0, 0, 1]
self.change.color = [0, 0, 0, 1]
self.percnt.color = [0, 0, 0, 1]
print(self)
class MyTextField(MDTextField):
pass
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "BlueGray"
return Builder.load_file('MyStocks.kv')
MainApp().run()
As it is it does not work. is this something that could be made to work or am I being too optimistic. I will also be needing to set Id's for all the labels.
EDIT: The situation is that I do not know how to update the values. In the python file the labels have names which I can address fom the python file (as you can see from the demo). Now, when the class is instantiated in the .kv file the complete layout gets and id. The question is how do I change the values of the labels using the id of the layout and the names of the labels. Bear in mind the layout will be instantiated multiple times.
I thank you in advance for any assistance on this. Thanks, Ray.
If I understood your issues properly, you just need a dynamic class. With dynamic class you can create an object with or without some propertie(s) that can be used with little to no further modifications. In kvlang it is even easier to build and modify the class (afterwards).
First create a dynamic class with some deterministic (here, predetermined or fixed no. of) properties in python as,
class MyRowBox(MDBoxLayout):
name = StringProperty("NAME")
value = StringProperty("Value")
change = StringProperty("Change")
percnt = StringProperty("Chg %")
Then design it in kvlang as,
<MyRowBox>:
md_bg_color: [0.5, .7, 0.2, 1]
size_hint_y: None
height: "30dp"
Widget:
size_hint_x : None
width: "20dp"
MDLabel:
color: 72/255,89/255,89/255,1
color: 0,0,0,1
text: root.name
halign: 'left'
size_hint: None, 1
width: "100dp"
MDLabel:
color: (0,0,0,1)
text: root.value
MDLabel:
color: (0,0,0,1)
text: root.change
MDLabel:
color: (0,0,0,1)
text: root.percnt
Thus your modified code in .kv file should now look like,
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
title: "My Stock Tickers"
left_action_items: [["menu", lambda x: x]]
type: 'top'
MDBoxLayout:
size_hint: None, None
size: "400dp", "100dp"
pos_hint: {"center_x": 0.5}
#elevation: 20
padding: 25
spacing: 25
md_bg_color: [0, .7, 1, 1]
#Widget:
#size_hint_y : None
#height: 10
MDLabel:
text: "Enter Ticker"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
MDTextFieldRound:
#id: user
width: 30
font_size: 18
#padding_y: 15
spacing: '20dp'
MDFIconButton:
user_font_size: "15sp"
icon: "plus"
opposite_colors: True
elevation: 8
md_bg_color: 1, 0, 0, 1
spacing: '20dp'
MDLabel:
id: t_price
text: "000.00"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
padding_y: 10
MDLabel:
id: t_change
text: "00.00"
font_size: 15
halign: "center"
size_hint_y: None
height: self.texture_size[1]
padding_y: 10
MyRowBox: # Same class as a title row
# due to its initilization style.
# Change it if you need to.
MyRowBox:
id: row1
name: "Dow"
value: "000.000"
change: "000.000"
percnt: "0.01%"
MyRowBox:
id: row2
name: "Dow"
value: "000.000"
change: "000.000"
percnt: "0.01%"
MyRowBox:
id: row3
name: "Dow"
value: "000.000"
change: "000.000"
percnt: "0.01%"
MyRowBox:
id: row4
name: "Dow"
value: "000.000"
change: "000.000"
percnt: "0.01%"
<MyRowBox>:
md_bg_color: [0.5, .7, 0.2, 1]
size_hint_y: None
height: "30dp"
Widget:
size_hint_x : None
width: "20dp"
MDLabel:
color: 72/255,89/255,89/255,1
color: 0,0,0,1
text: root.name
halign: 'left'
size_hint: None, 1
width: "100dp"
MDLabel:
color: (0,0,0,1)
text: root.value
MDLabel:
color: (0,0,0,1)
text: root.change
MDLabel:
color: (0,0,0,1)
text: root.percnt
Update (usage case):
The usage case of this class in python could be like,
# Please add the rest / necessary blocks.
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "BlueGray"
self.root = Builder.load_string(kv)
return self.root
def on_start(self):
box1 = self.root.ids.row1
box2 = self.root.ids.row2
# etc.
for i, box in enumerate([box1, box2, ]):
box.name = str(i+1)
box.value = str(100+i)
box.change = str(i)
box.percnt = f"{i/100:0.2%}"
MainApp().run()
Note:
I used dp for better consistency. You may change it.
You perhaps need the class MyBox no more.
We are developing an app with many screens and much kv code, using lazy loading template by Kulothungan on GitHub and it is fine, besides one screen, the calculator. It takes 10 seconds or more to load on Android, and we don't understand why!
Part of code:
# ----- Python Class: -----
class CustomRoundButton(ButtonBehavior, CircularRippleBehavior, CircularElevationBehavior, MDFloatLayout):
pass
# ----- KV Class: -----
<Calculator>
name: "calculator"
MDBoxLayout:
padding: "35dp"
spacing: "25dp"
orientation: "vertical"
MDLabel:
id: calclabel
text: "0"
halign: "right"
valign: "center"
font_style: "H2"
size_hint_y: .4
pos_hint_y: .5
GridLayout:
cols: 4
spacing: "15dp"
CustomRoundButton:
pos_hint: {"center_x": .5, "center_y": .5}
radius: lbl.texture_size[0] + self.height / 2
md_bg_color: app.theme_cls.accent_color
size_hint_y: None
height: self.width
elevation: 8
on_release:
root.calcformula = ""
calclabel.text = "0"
Label:
id: lbl
text: "AC"
font_size: root.height / 20
-text_size: None, None
size_hint: None, None
size: self.texture_size[0] + dp(50), self.texture_size[0] + dp(50)
pos_hint: {"center_x": .5, "center_y": .5}
color: 1, 1, 1, 1
...
Here is a link to the whole screen code
Any help would be really appreciated!
Thanks!
My App has 3 screens to navigate through with the 'ActionBar'. I have named each screen in kv file, one is 'track' the other 'pess'. These are the two I need help with.
I created a radiobutton widget in my 'pess' screen class (pictures below) So I could add email address.
In my 'track' screen class I have all the data I'd like to send over email but I think I'm over complicating things. I want to link the active radiobutton from my 'pess' screen to my 'track' screen def send function...
my Main.py looks like this
class ScreenGenerator(ScreenManager):
pass
class PessQuestions(Screen):
email = {}
path = ''
def loadEmails(self, *args):
self.path = App.get_running_app().user_data_dir + '/'
try:
with open(self.path + 'email.json', 'r') as data:
self.email = json.load(data)
except FileNotFoundError:
pass
def saveEmails(self, *args):
print(self.ids.name.text, type(self.ids.name.text))
print(self.ids.address.text, type(self.ids.address.text))
self.email[self.ids.name.text] = self.ids.address.text
self.path = App.get_running_app().user_data_dir + '/'
with open(self.path + 'email.json', 'w') as email_address_json:
json.dump(self.email, email_address_json)
print('saveEmails')
self.ids.address.text = ''
self.ids.name.text = ''
self.ids.info.clear_widgets()
self.on_pre_enter() # refresh screen
def delete_email(self, check):
address = check.ids.who_name.text
del self.email[address]
self.ids.info.remove_widget(check)
self.saveEmails()
##########################################################
########### PRE ENTER ####################################
def on_pre_enter(self):
self.ids.info.clear_widgets()
self.loadEmails()
try:
for name, mail in self.email.items():
self.ids.info.add_widget(Checkboxes(name=name, mail=mail, email=self.email))
except ValueError:
print('VALUE ERROR: Label.text accept only "str"')
self.ids.pess_date.text = strftime('[b]%A[/b], %B %Y') # time and date
##########################################################
########### PRE LEAVE ####################################
def on_pre_leave(self):
self.ids.info.clear_widgets()
self.saveEmails()
class Checkboxes(BoxLayout):
def __init__(self, name='', mail='', email='', **kwargs):
super().__init__(**kwargs)
self.ids.who_name.text = name
self.ids.who_email.text = mail
def on_checkbox_Active(self, checkboxInstance, isActive):
address = ''
if isActive:
'''
Email is used for recipient
'''
name = self.ids.who_name.text
email = self.ids.who_email.text
print('Email Set!')
return email
else:
'''
Nothing happens, email is not used
'''
##########################################################
######## TRACKERS WINDOWS ################################
##########################################################
class Trackers(Screen):
email = {'davi': 'example#gmail.com'}
storage = {}
pess_storage = {}
path = ''
def on_pre_enter(self):
self.path = App.get_running_app().user_data_dir + '/'
self.loadData()
for tracker, num in self.storage.items():
self.ids.track.add_widget(Tracker(text=tracker, number=num))
def on_pre_leave(self):
self.ids.track.clear_widgets()
self.saveData()
def saveData(self, *args):
with open(self.path + 'data.json', 'w') as data:
json.dump(self.storage, data)
def loadData(self, *args):
try:
with open(self.path + 'data.json', 'r') as data:
self.storage = json.load(data)
print(self.storage)
except FileNotFoundError:
pass
def savePESS(self, PESS):
self.pess_storage['physical'] = PESS.ids.phy_text.text
self.pess_storage['emotional'] = PESS.ids.emo_text.text
self.pess_storage['spiritual'] = PESS.ids.spi_text.text
self.pess_storage['sexual'] = PESS.ids.sex_text.text
self.pess_storage['comment'] = PESS.ids.comment.text
def save_text(self, tracker, text_input, *args):
tracker.ids.label.text = text_input.text
self.storage[text_input.text] = '0'
self.saveData()
self.loadData()
print('testing')
def send(self, PESS):
self.path = App.get_running_app().user_data_dir + '/'
with open(self.path + 'bat', 'r') as bat:
login = bat.read()
davi = self.email['davi']
mail = PESS.ids.who_email.text
#kevin = self.email['kevin'] # instead of this I'd like to have this variable linked to
gmail = GMail(davi, login)
day = strftime("%a, %b %d, %Y")
tracker_message = 'PESS\n'
subject_message = f"Subject: PESS {day}"
for pess, txt in self.pess_storage.items():
tracker_message += f"\t{pess.title()}: {txt}\n"
for tracker, numbers in self.storage.items():
tracker_message += f"\n{numbers} ---> {tracker}\n"
message = f"{subject_message}\n\n{tracker_message}"
msg = Message(f'PESS | {day}', to=mail, text=message)
gmail.send(msg)
self.sent_confirmation(f'{self.ids.who_name.text}: {mail}')
def sent_confirmation(self, recipient):
box = BoxLayout(orientation='vertical', padding=40, spacing=5)
pop = Popup(title='Email Sent', content=box, size_hint=(None,None), size=(self.width, self.width/2))
info = Label(text=f'Congrats, {recipient} has recieved an email.')
box.add_widget(info)
pop.open()
self.saveData()
class Tracker(BoxLayout):
def __init__(self, text='', number='', **kwargs):
super().__init__(**kwargs)
self.ids.label.text = text
self.ids.count_add.text = number
class Pess(App):
def build(self):
Config.set('graphics', 'width', '600')
Config.set('graphics', 'height', '800')
from kivy.core.window import Window
Window.clearcolor = get_color_from_hex('#262829')
return ScreenGenerator()
if __name__ == '__main__':
Pess().run()
kv file
#: import rgba kivy.utils.get_color_from_hex
#: import CheckBox kivy.uix.checkbox
<Label>:
font_size: '17dp'
<MenuButton#ButtonBehavior+Label>:
canvas.before:
Color:
rgba: 0.1, 0.5, 0.7, 1
Ellipse:
pos: self.pos
size: self.height, self.height
Ellipse:
pos: self.x + self.width - self.height, self.y
size: self.height, self.height
Rectangle:
pos: self.x + self.height / 2, self.y
size: self.width - self.height, self.height
<RoundButton#ButtonBehavior+Label>:
canvas.before:
Color:
rgba: 0.8, 0.3, 0.1, 1
Ellipse:
pos: self.width / 2.265, self.y + 130
size: self.height - self.height / 1.5, self.height / 3
<MenuButton2#ButtonBehavior+Label>:
canvas.before:
Color:
rgba: 0.8, 0.3, 0.1, 1
Ellipse:
pos: self.pos
size: self.height, self.height
Ellipse:
pos: self.x + self.width - self.height, self.y
size: self.height, self.height
Rectangle:
pos: self.x + self.height / 2, self.y
size: self.width - self.height, self.height
<FloatButton#ButtonBehavior+FloatLayout>:
id: float_root
size_hint: (None, None)
text: '[b]+[/b]'
font_size: '48dp'
btn_size: (140,140)
size: (140,140)
bg_color: (0.8, 0.3, 0.1, 1)
pos_hint: {'x': 5.4, 'y': .17}
Button:
text: float_root.text
font_size: '14dp'
#allow_stretch: True
markup: True
size_hint: (None, None)
size: float_root.btn_size
pos_hint: float_root.pos_hint
background_normal: ''
background_color: (0,1,0,0)
canvas.before:
Color:
rgba: float_root.bg_color
Ellipse:
pos: self.pos
size: self.size
<TrackerButton#Button>:
background_color: 0,0,0,0
<ScreenGenerator>:
Menu:
name: 'menu'
Trackers:
name: 'track'
PessQuestions:
name: 'pess'
<Menu>:
BoxLayout:
orientation: 'vertical'
padding: 20
spacing: 30
Image:
source: 'book.png'
allow_strech: True
Label:
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
height: 1
MenuButton:
text: 'Enter Trackers'
height: dp(60)
size_hint_y: None
background_image: ''
background_color: rgba('#637075')
on_release: app.root.current = 'track'
MenuButton:
text: 'Enter PESS'
height: dp(60)
size_hint_y: None
background_image: ''
background_color: rgba('#637075')
on_release: app.root.current = 'pess'
Label:
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
height: 1
Label:
id: time
text: ''
markup: True
<PessQuestions>:
BoxLayout:
orientation: 'vertical'
pos_hint: {'top': 1}
ActionBar:
height: self.minimum_height + dp(50)
size_hint_y: None
background_image: ''
background_color: rgba('#ffffff') # rgba('#0B3242')
ActionView:
ActionPrevious:
title: '[b]PESS[/b]'
font_size: '17dp'
color: rgba('#AFB7BA')
markup: True
on_release: app.root.current = 'track'
ActionButton:
text: 'SEND'
color: rgba('#AFB7BA')
on_release: app.root.get_screen('track').send(root) # if .send() function is on another class outside of 'class PessQuestions' use the .get_screen() to locate the right screen class
#on_release: app.root.send()
ActionButton:
text: 'TRACKER'
color: rgba('#AFB7BA')
on_release: app.root.current = 'track'
ActionButton:
text: 'HOME'
color: rgba('#AFB7BA')
on_release: app.root.current = 'menu'
BoxLayout:
orientation: 'vertical'
padding: dp(10)
spacing: dp(12)
pos_hint: {'top': 1}
TextInput:
id: phy_text
hint_text: 'Physical'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
TextInput:
id: emo_text
hint_text: 'Emotional'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
TextInput:
id: spi_text
hint_text: 'Spiritual'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
TextInput:
id: sex_text
hint_text: 'Sexual'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
TextInput:
id: comment
hint_text: 'Leave a comment'
size_hint_y: None
height: self.minimum_height + dp(100)
MenuButton:
id: save_pess
text: 'Save PESS'
height: dp(60)
size_hint_y: None
background_image: ''
on_press: self.text = 'SAVED!'
on_release: app.root.get_screen('track').savePESS(root)
MenuButton2:
text: 'Clear PESS'
height: dp(60)
size_hint_y: None
background_image: ''
on_press: root.ids.save_pess.text = 'Save PESS'
on_release: root.resetPESS()
MenuButton:
text: 'Send Report'
color: rgba('#AFB7BA')
height: dp(60)
size_hint_y: None
background_image: ''
on_release: app.root.get_screen('track').send(root) # if .send() function is on another class outside of 'class PessQuestions' use the .get_screen() to locate the right screen class
#on_release: app.root.send()
Label:
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
height: 1
Label:
text: '[b]Physical, Emotional, Spiritual, Sexual[/b] | These principles when lived with a full purpose of heart will invite the Holy Ghost into your lives.'
markup: True
text_size: self.width, None
size_hint: 1, None
height: self.texture_size[1]
Label:
id: pess_date
text: ''
markup: True
Label:
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
height: 1
# Label & Checkbox creation | for selecting email address
Label:
text: "EMAIL"
text_size: self.width, None
size_hint: 1, None
height: self.texture_size[1]
ScrollView:
BoxLayout:
id: info
orientation: 'vertical'
padding: dp(5)
spacing: dp(7)
#size_hint_y: None
#height: self.minimum_height + dp(50)
TextInput:
id: name
hint_text: 'Name'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
TextInput:
id: address
hint_text: 'Email Address'
size_hint_y: None
height: self.minimum_height + dp(7)
multiline: False
MenuButton:
id: save_email
text: 'Save Email'
height: dp(60)
size_hint_y: None
background_image: ''
on_release: root.saveEmails()
<Checkboxes>:
CheckBox:
group: 'emails'
color: .294, .761, .623
on_active: root.on_checkbox_Active(self, self.active)
#on_active: app.root.get_screen('pess').on_checkbox_Active(self, self.active)
size_hint_x: .50
Label:
id: who_name
text: ''
text_size: self.width, None
halign: 'left'
Label:
id: who_email
text: ''
text_size: self.width, None
halign: 'left'
Button:
text: '[b]X[/b]'
markup: True
size_hint_x: None
width: dp(20)
on_release: app.root.get_screen('pess').delete_email(root)
<Trackers>:
BoxLayout:
orientation: 'vertical'
ActionBar:
height: self.minimum_height + dp(50)
size_hint_y: None
background_image: ''
background_color: rgba('#ffffff') #rgba('#0B3242')
ActionView:
ActionPrevious:
title: '[b]TRACKERS[/b]'
font_size: '17dp'
color: rgba('#AFB7BA')
markup: True
on_release: app.root.current = 'pess'
ActionButton:
text: 'RESET'
color: rgba('#AFB7BA')
on_release: root.reset_pop()
ActionButton:
text: 'PESS'
color: rgba('#AFB7BA')
on_release: app.root.current = 'pess'
ActionButton:
text: 'HOME'
color: rgba('#AFB7BA')
on_release: app.root.current = 'menu'
ScrollView:
BoxLayout:
id: track
orientation: 'vertical'
padding: dp(10)
spacing: dp(15)
size_hint_y: None
height: self.minimum_height
BoxLayout:
size_hint_y: None
height: dp(100)
Button:
text: '+'
font_size: '56dp'
size_hint_y: None
background_image: ''
background_color: (0,0,0,0)
on_release: root.addWidget()
#BoxLayout:
#FloatButton:
# pos_hint_x: None
# pos_hint_y: None
# on_release: root.addWidget()
<Tracker>:
count_add: count_add
name: name
size_hint_y: None
height: 130
canvas.before:
Color:
rgba: 0.1, 0.5, 0.7, 1
Rectangle:
pos: self.pos[0] + self.height/2, self.pos[1]
size: self.size[0] - self.height, self.height
Ellipse:
pos: self.pos[0], self.pos[1]
size: self.height, self.height
Ellipse:
pos: self.pos[0] + self.width - self.height, self.pos[1]
size: self.height, self.height
TrackerButton:
text: '[b]X[/b]'
markup: True
size_hint_x: None
width: 120
on_release: app.root.get_screen('track').delete_storage(root)
Label:
id: name
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_x: None
width: 1
TrackerButton:
id: label
font_size: '16dp'
on_release: app.root.get_screen('track').change_name(root)
TrackerButton:
id: count_add
font_size: '16dp'
text: '0'
size_hint_x: None
width: 120
on_release: app.root.get_screen('track').add_num(root)
Label:
canvas.before:
Color:
rgba: (1,1,1,.7)
Rectangle:
size: self.size
pos: self.pos
size_hint_x: None
width: 1
TrackerButton:
text: '[b]-[/b]'
font_size: '24dp'
markup: True
size_hint_x: None
width: 120
on_release: app.root.get_screen('track').subtract_num(root)
I had my code running really well, but all of the email sending information was hardcoded. I wanted to give the user options to input an email address and send it to that address.
I added the class Checkboxes which get's created every time I add a name and email address and hit the "Save Email" It's grouped so they are radio buttons.
I can't seem to connect the email address to my send function on the class Trackers... I hope all of this makes some sense. I might be overly complicating things for myself. I could use some help please. Thank you.
Just came across this question and since I am short on time I wont be able to help you completely. If you ever want to access widgets inside and outside of your class screens you need to have a shared parent for the both of them. In your main py file you can have something like this defined.
class MainInterface(BoxLayout):
def __init__(self, **kwargs):
super(MainInterface, self).__init__(**kwargs)
class WindowManager(ScreenManager):
pass
class HomeWindow(Screen):
...
class TrackerWindow(Screen):
...
sm = WindowManager()
screens = [HomeWindow(name="Home"), TrackerWindow(name="TrackerWindow")]
for screen in screens:
sm.add_widget(screen)
class MyMainApp(App):
def build(self):
root = MainInterface()
return root
The way you use your kv file from now on will be different from what you are used to. Your kv file can look something like this. I'll be using different example uses for one button to save time for myself.
<MainInterface>:
WindowManager:
id: screenmanager
HomeWindow:
id: homewindow
...
Button:
pos_hint:{"x":0,"top":1}
size_hint: 0.125, 0.1
text: "Some Stuff"
font_size: (root.width**1 + root.height**1) / 10**2
on_release:
root.ids['trackerwindow'].send(YourData)
root.ids['homewindow'].access_user_inputs(self.parent.user_inputs)
root.ids['screenmanager'].transition.direction = "left"
root.ids['screenmanager'].current="TrackerWindow"
TrackerWindow:
id: trackerwindow
...
notice how on the homescreen button to get information from its own screen you can't just use root.access_user_inputs(root.user_inputs) you created a parent tree so you use self.parent if you want to access a function from your windowmanager you would do a similar set up but use self.parent.parent. I hope this helps and if you have questions please ask and I'll be able to further help you later.
I recently updated kivyMD from 0.102.1 to 0.103.0 and i'm getting the following error:
raise FactoryException('Unknown class <%s>' % name)
kivy.factory.FactoryException: Unknown class
But when go back to version 0.102.1 everything works just fine. I'll post the code below but I just wanted to know if I wanted to update to 0.103.0 what do I need to change? I've tried to do some research but unable to find something that will fix the problem.
.py
#imported from kivy framework
from kivy.app import App
from kivymd.app import MDApp
from kivy.app import App
from datetime import datetime
from datetime import timedelta
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
import weatherGrab
from weatherGrab import weatherCheck
import os
#1st screen
class Login_Screen(Screen):
#Takes user input from the .KV file, converts it to string and verifies if its a saved login
def verify_credentials(self):
Username = self.ids.Username_userInput
Password = self.ids.Password_userInput
Username_string = Username.text
Password_string = Password.text
#Allows the variable to be used in another class and method
Login_Screen.verify_credentials.GGG = Username.text
#checks if user input is equal to temp database
if self.ids["Username_userInput"].text == "Username" and self.ids["Password_userInput"].text == "Password":
self.manager.current = "Homepage_Screen"
print("USER LOGIN DATA: " + Username_string +" "+Password_string)
weatherGrab.weatherCheck()
#print('CURRENT WEATHER - London','\n',weatherCheck.currentWeather,'\n' ,weatherCheck.temp)
#print('HERE',var1)
#x = dir(platform) prints all function from that lib
#after log in, sets user input to empty so the next user can login
def clean(self):
self.ids["Username_userInput"].text = ""
self.ids["Password_userInput"].text = ""
#saving user inputs to a text file (temp database)
def save_data(self):
Username = self.ids.Username_userInput
Password = self.ids.Password_userInput
Username_string = Username.text
Password_string = Password.text
TextDoc = open("UserLogin.txt", "a")
username = Username_string
password = Password_string
if username == '' and password == '':
pass
else:
TextDoc.write("\n"+username+","+password)
TextDoc.close()
#loads data from the file (debugging/testing)
def load_data(self):
f = open("UserLogin.txt", "r")
print("FROM TEXT FILE:"+ f.read())
#2nd screen
class Homepage_Screen(Screen):
#Event dispatcher to load data when user enters the second screen
def on_enter(self):
self.load_info()
self.weather()
def weather(self):
self.ids["temp"].text = weatherCheck.temp
self.ids["date"].text = weatherCheck.currentDate
#Text prints in termial for testing/debugging
def load_info(self):
print("PASSING USERNAME TO HOMEPAGE: "+Login_Screen.verify_credentials.GGG)
self.ids["USERNAME"].text = "Welcome"+" "+Login_Screen.verify_credentials.GGG
#Saves User input from the notes textinput
def save_notes(self):
UserNotes = self.ids.UserInput_notes
UserNote = UserNotes.text
TextDoc = open("UserLogin.txt", "a")
TextDoc.write("," + UserNote)
TextDoc.close()
#3rd screen
class Application_Screen(Screen):
pass
#4th screen
class Logout_Screen(Screen):
def newline(self):
TextDoc = open("UserLogin.txt", "a")
TextDoc.write("\n")
TextDoc.close()
def forcequit(self):
exit()
#class for all screens
class ScreenManagement(ScreenManager):
pass
class MainApp(MDApp):
def build(self):
#declaring time from python, and making it refresh every second
self.now = datetime.now()
Clock.schedule_interval(self.update_clock, 1)
def update_clock(self, *args):
self.now = self.now + timedelta(seconds=1)
#Allows for time to be shown on all screens
self.root.get_screen("Homepage_Screen").ids["CurrentTime"].text = self.now.strftime("%H:%M:%S")
self.root.get_screen("Logout_Screen").ids["CurrentTime"].text = self.now.strftime("%H:%M:%S")
self.root.get_screen("Login_Screen").ids["CurrentTime"].text = self.now.strftime("%H:%M:%S")
#print(self.now.strftime("%H:%M:%S"))
MainApp().run()
.kv
#:kivy 1.0
#:import hex kivy.utils.get_color_from_hex
#styles that will apply to all intences for each tag
<MDRaisedButton>:
font_size:18
<Label>:
color: 0,0,0,1
#declaring screen managers and printing them in this order
ScreenManagement:
Login_Screen:
name:"Login_Screen"
id: woow
Homepage_Screen:
name:"Homepage_Screen"
Application_Screen:
name:"Application_Screen"
Logout_Screen:
name:"Logout_Screen"
#style for login screen
<Login_Screen>:
#background color
FloatLayout:
spacing: 10
canvas.before:
Color:
rgba: hex('#eff3fa')
Rectangle:
size: self.size
pos: self.pos
#Navbar
MDToolbar:
id: fb
pos_hint: {'center_x': 0.5, 'top':1.0}
size_hint_y:None
height: 50
title: "Virtual Assistant"
md_bg_color: hex('#132843')
Label:
id: CurrentTime
font_size:18
size_hint_x: .1
color: (1,1,1,1)
#login container
#background color/positioning
BoxLayout:
spacing: 10
orientation: 'vertical'
padding: 50
canvas.before:
Color:
rgba: hex('#000')
Rectangle:
size: self.size
pos: self.pos
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint: 0.33, None
size_hint_min_x: 200
height: self.minimum_height
#LOGIN CONTENT
#logo
Image:
source: 'Logo.png'
size_hint: None, None
size: 100, 100
pos_hint: {'center_x': 0.5, 'center_y': 0.0}
MDTextField:
id: Username_userInput
hint_text:"Username"
text:"Username"
line_color_normal: 0,0,0,1
MDTextField:
id: Password_userInput
hint_text:"Password"
text:"Password"
password: True
line_color_normal: 0,0,0,1
#color_mode:'accent'
Button:
text:"Login"
size_hint_y: None
height: 60
padding: 10,10
background_color: (2.08, 2.40, 1.92,1)
size_hint: 0.40, None
pos_hint: {'center_x': 0.5, 'center_y': 0.0}
on_press: root.verify_credentials() , root.save_data(), root.clean(), root.load_data()
#style for Homepage screen
<Homepage_Screen>:
#SIDEBAR BUTTONS
NavigationLayout:
id: nav_layout
MDNavigationDrawer:
drawer_logo:'Logo.png'
NavigationDrawerSubheader:
id: USERNAME
NavigationDrawerIconButton:
icon:"home"
text:"Homepage"
theme_text_color: 'Custom'
on_release:
screen_manager.current = "Homepage"
NavigationDrawerIconButton:
icon:'application'
text: "Application"
on_release:
screen_manager.current = "Application"
NavigationDrawerIconButton:
icon: 'dictionary'
text: "Dictionary"
on_release:
screen_manager.current = "Dictionary"
MDRectangleFlatIconButton:
icon:'logout'
text: "Logout"
#on_press: root.clean()
on_release: app.root.current = "Logout_Screen"
size_hint: 1, None
font_size:20
text_color: 0,0,0,1
#BACKGROUND
FloatLayout:
spacing: 10
canvas.before:
Color:
rgba: hex('#eff3fa')
Rectangle:
size: self.size
pos: self.pos
#NAVBAR
MDToolbar:
id: fb
pos_hint: {'center_x': 0.5, 'top':1.0}
size_hint_y:None
height: 50
title: "Virtual Assistant"
md_bg_color: hex('#132843')
left_action_items: [['menu', lambda x: root.ids.nav_layout.toggle_nav_drawer()]]
Label:
id: CurrentTime
size_hint_x: .1
font_size:18
color: (1,1,1,1)
#SIDEBAR SCREEN STYLE
ScreenManager:
id: screen_manager
#HOMEPAGE SCREEN STYLE
Screen:
name: "Homepage"
BoxLayout:
spacing: 10
orientation: 'vertical'
padding: 10
canvas.before:
Color:
rgba: (1,1,1,.8)
Rectangle:
size: self.size
pos: self.pos
pos_hint: {'center_x': 0.5, 'top': (root.height - fb.height)/root.height}
size_hint: 0.3, None
height: 35
GridLayout:
rows: 3
cols: 3
padding: 10
spacing: 15
#pos_hint: {"center_x":0.6, "center_y":0.0}
Label:
id:date
color: (0,0,0,1)
size_hint_x: 2
Label:
id:temp
color: (0,0,0,1)
size_hint_x: 2
Label:
text:'icon'
color: (0,0,0,1)
size_hint_x: 2
BoxLayout:
orientation: 'horizontal'
spacing: 10
padding: 10
canvas.before:
Color:
rgba: (1,1,1,1)
Rectangle:
size: self.size
pos: self.pos
size_hint: 0.8, None
height: 60
pos_hint: {'center_x': .5, 'center_y':.5}
TextInput:
height:60
size_hint: 5, None
focus: True
multiline: False
font_size: 25
padding_y:15
background_color: 1,1,1,0
foreground_color: 0,0,0,1
pos_hint:{'center_x':0, 'center_y':0.5}
MDRectangleFlatIconButton:
icon:'search-web'
height:45
text_color: 0,0,0,1
md_bg_color: hex("#D0F0C0")
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
Label:
text:'Search'
font_size:18
I am trying to make an app that shows one image. When I click in some button, the function will change the source of this image, therefore this image will change. So, I tried only change the line image.source, I think the correct way to do this is using a stringproperty, but I also have not had success with it. So, my code is:
.py
class PrimeiroScreen(Screen):
def __init__(self, **kwargs):
self.name = 'um'
super(Screen,self).__init__(**kwargs)
fonte = StringProperty('cafe.jpg')
def fc1(self):
self.ids.image.source = (fonte)
self.ids.image.fonte = "cafe.jpg"
#self.ids.image.source = "cafe.jpg"
class MyImage(Image):
fonte = StringProperty()
class RootScreen(ScreenManager):
pass
and .kv:
<RootScreen>:
PrimeiroScreen:
<PrimeiroScreen>:
StackLayout:
orientation: 'tb-rl'
ScrollView:
#size: 100, 100
#pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10, 10
spacing: 5, 5
size_hint: (None, None)
size_hint_y: None
width: 500
height: self.minimum_height
Button:
text: "1"
#color: 0,0,0,1
font_size: '20dp'
size: (200, 40)
size_hint: (None, None)
on_release: root.fc1()
AnchorLayout:
Image:
source:'logo.jpg'
id: image
I am learning about AnchorLayout, and StackLayout, so it's not working.
Very thanks everyone, for awser my newbie question. Nice weekend.
The thing is with your current code there is no fonte defined(at least for me with copy&paste), you need to use self.fonte.
But anyway, you should access the source directly, otherwise you'd need to make another function that handles your property updating and doing something when it changes i.e. passing it to source, which already is a StringProperty, therefore you'd go really around the solution until you reached it.
<RootScreen>:
PrimeiroScreen:
<PrimeiroScreen>:
StackLayout:
orientation: 'tb-rl'
ScrollView:
#size: 100, 100
#pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10, 10
spacing: 5, 5
size_hint: (None, None)
size_hint_y: None
width: 500
height: self.minimum_height
Button:
text: "1"
color: 0,0,0,1
font_size: '20dp'
size: (200, 40)
size_hint: (None, None)
on_release: image.source='newcafe.png'
MyImage:
source: 'cafe.jpg'
id: image