I want to write a program for the user to add a profile picture to the KivyMD application using the button. My knowledge of writing a Python program to do this is limited. Please help me.
I want to write a program for the user to add a profile picture to the KivyMD application using the button. My knowledge of writing a Python program to do this is limited. Please help me.
You can use the MDFileManager class to open up a file browser that returns the location of the image you have selected, for this example to work, make sure you have an image called "i.jpeg" (you can change that in the source code), if you don't have that image in the same directory (same folder) where you have saved this python script, then this example will fail:
from kivy.core.window import Window
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.filemanager import MDFileManager
from kivymd.toast import toast
from kivymd.utils.fitimage import FitImage
from kivy.properties import (
StringProperty,
BooleanProperty,
ObjectProperty,
NumericProperty,
ListProperty,
OptionProperty,
)
KV = '''
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
title: "Black-Hands"
left_action_items: [['menu', lambda x: None]]
elevation: 10
MDFloatLayout:
MDCard:
id: cbor
orientation: "vertical"
size_hint: .95, None
pos_hint: {"center_x": .5, "center_y": .9}
#background: "bgg.png"
GridLayout:
cols: 2
MDLabel:
id: user20
markup: True
text: "\\n\\n[b][color=000000] JOSUE CARRANZA (jbsidis)\\n[/b] [color=000000]Cód. de Vendedor: 39213\\n[color=000000] Idioma: \\n"
font_style: "Caption"
halign: "left" #"left" #"right"
height: self.texture_size[1]
Image: #FitImage
id: pic
size_hint: None, None
source: "i.jpeg"
height: root.ids.cbor.height
## source: root.newpic #"i.jpeg" #"xbay.png"
## size_hint: None, None
## height: root.ids.cbor.height
MDRoundFlatIconButton:
id: n1
text: "Change picture"
icon: "pencil"
disabled: True
pos_hint: {'center_x': .5, 'center_y': .6}
on_release: app.file_manager_open()
MDCard:
padding: dp(5)
size_hint: 1,.1
MDLabel:
markup: True
text: "[b]Subscribe and Watch my KivyMD Videos: [/b]https://www.youtube.com/channel/UCIMmPyY7XjWHk1AHlR_UdWQ"
<ProfilePicture>:
## id: pic
source: root.newpic #"i.jpeg" #"xbay.png"
size_hint: None, None
## height: root.ids.cbor.height
'''
class ProfilePicture(FitImage):
newpic=StringProperty()
import os
from kivy.clock import Clock
class Example(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Window.bind(on_keyboard=self.events)
self.manager_open = False
def nn(self):
self.file_manager = MDFileManager()
self.file_manager.exit_manager=self.exit_manager
self.file_manager.select_path=self.select_path
self.root.ids.n1.disabled=False
#preview=False
def build(self):
Clock.schedule_once(lambda x: self.nn(),3)
return Builder.load_string(KV)
def chpic(self,new):
if os.path.isfile(new)==True:
self.root.ids.pic.source=new
print("The pictura was changed to:",self.root.ids.pic.source)
def file_manager_open(self):
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def select_path(self, path):
self.exit_manager()
print(path)
if os.path.isfile(path)==True:
Clock.schedule_once(lambda x:self.chpic(path),1)
#toast(path) #here the location for the image file will be returned
return path
def exit_manager(self, *args):
self.manager_open = False
self.file_manager.close()
def events(self, instance, keyboard, keycode, text, modifiers):
if keyboard in (1001, 27):
if self.manager_open:
self.file_manager.back()
return True
Example().run()
This example comes from me (jbsidis) and it has parts from the kivymd documents, however I changed a lot of things to make it work, if you only copy and paste the MDFileManager example from the docs, it may fail, that's why in this example you will see that the class MDFileManager is located and executed after 3 seconds (this is needed because of a "kivymd bug"), subcribe to my channel in youtube: https://www.youtube.com/channel/UCIMmPyY7XjWHk1AHlR_UdWQ
@jbsidis Josué Carranza - Sir, first I tried the code you have given above, It has been worked successfully. But when I add that to my code the file manager can be opened. But the picture can't be changed. There was a problem occurred.
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
I think the problem is with my code. But I can't understand what's the problem. How would I solve that?
Here is my code
.kv file
screen_helper = """
ScreenManager:
Studio:
<Studio>:
name : 'studio'
BoxLayout:
orientation:'vertical'
MDToolbar:
elevation : 8
adaptive_height: True
height: '350dp'
md_bg_color: 0,0,0,.000001
MDFloatLayout:
FitImage:
id: cover_pic
orientation: "vertical"
size_hint: 1, .75
pos_hint: {"center_x": .5, "center_y": 1}
source: "Photos/3.jpg"
FitImage:
id: profile_pic
size_hint: 1,1
size_hint: None, None
source: "Photos/Kusal.png"
pos_hint: {"center_x": .172, "center_y": .583}
radius: 60, 60, 60, 60
TooltipMDIconButton:
tooltip_text : 'Edit Cover Picture'
id: edit_cover_pic
icon: "image-edit-outline"
disabled: False
pos_hint: {'center_x':0.95,'center_y':0.97}
user_font_size: "25sp"
on_release: app.file_manager_open()
TooltipMDIconButton:
tooltip_text : 'Edit Profile Picture'
id: edit_profile_pic
icon: "image-edit-outline"
disabled: False
pos_hint: {'center_x':0.95,'center_y':0.585}
user_font_size: "25sp"
on_release: app.file_manager_open()
TooltipMDIconButton:
tooltip_text : 'Edit Bio'
id: edit_profile_pic
icon: "pencil"
disabled: False
pos_hint: {'center_x':0.91,'center_y':0.585}
user_font_size: "25sp"
on_release: app.file_manager_open()
MDIconButton:
icon: 'arrow-left'
pos_hint: {'center_x':0.03,'center_y':0.97}
user_font_size: "25sp"
theme_text_color : 'Custom'
text_color : 0,0,0,1
on_release :
root.manager.current = 'navigator'
root.manager.transition.direction = 'right'
MDIconButton:
icon: 'home'
pos_hint: {'center_x':0.08,'center_y':0.97}
user_font_size: "25sp"
theme_text_color : 'Custom'
text_color : 0,0,0,1
on_release :
root.manager.current = 'home'
root.manager.transition.direction = 'right'
I want to change the images of id : profile_pic and id : cover pic
.py file
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.app import MDApp
from widgets import screen_helper
from kivymd.toast import toast
from kivymd.uix.filemanager import MDFileManager
from kivy.properties import (
StringProperty,
BooleanProperty,
ObjectProperty,
NumericProperty,
ListProperty,
OptionProperty,
)
class Studio(Screen):
pass
import os
from kivy.clock import Clock
class Mode(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Window.bind(on_keyboard=self.events)
self.manager_open = False
def nn(self):
self.file_manager = MDFileManager()
self.file_manager.exit_manager=self.exit_manager
self.file_manager.select_path=self.select_path
#preview=False
def build(self):
Clock.schedule_once(lambda x: self.nn(), 3)
return Builder.load_string(screen_helper)
def edit_pic(self,new):
if os.path.isfile(new)==True:
self.root.ids.cover_pic.source=new
def file_manager_open(self):
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def select_path(self, path):
self.exit_manager()
print(path)
if os.path.isfile(path)==True:
Clock.schedule_once(lambda x:self.edit_pic(path),1)
toast(path) #here the location for the image file will be returned
return path
def exit_manager(self, *args):
self.manager_open = False
self.file_manager.close()
def events(self, instance, keyboard, keycode, text, modifiers):
if keyboard in (1001, 27):
if self.manager_open:
self.file_manager.back()
return True
Yes, I was analizing your code and I will give you the right code for your program, also, Read all comments in the code, I was adding notes so you can get more info about errors, my personal recommendation is, alway do a single python script (I mean do not divide the program in kv files and py files, unless you are using HotReloadViewer), so here is the code fixed:
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
try:
from widgets import screen_helper
except:
pass #ModuleNotFoundError: No module named 'widgets'
from kivymd.app import MDApp
from kivymd.uix.filemanager import MDFileManager
from kivymd.toast import toast
from kivymd.utils.fitimage import FitImage
from kivy.properties import (
StringProperty,
BooleanProperty,
ObjectProperty,
NumericProperty,
ListProperty,
OptionProperty,
)
class Studio(Screen):
#this is a good idea, to implement it, you should add it using clock
pass
KV = '''
Screen:
ScreenManager:
id: manager #this is needed
Screen:
name : 'studio'
MDFloatLayout:
Image: #if we use FitImage: is not good, because FitImage does not update images, but Image does
id: cover_pic
orientation: "vertical"
size_hint: 1, .75
pos_hint: {"center_x": .5, "center_y": 1}
source: "Photos/20190907_154525.jpg"
Image: #the FitImage: class does not update media, but Image does
id: profile_pic
size_hint: None, None
source: "Photos/pro.jpg"
pos_hint: {"center_x": .172, "center_y": .583}
radius: 60, 60, 60, 60
#
TooltipMDIconButton: #kivy.factory.FactoryException: Unknown class <TooltipMDIconButton>
tooltip_text : 'Edit Profile Picture'
id: edit_profile_pic
icon: "image-edit-outline"
disabled: True
pos_hint: {'center_x':0.95,'center_y':0.585}
user_font_size: "25sp"
on_release: app.file_manager_open_for_profile()
TooltipMDIconButton: #kivy.factory.FactoryException: Unknown class <TooltipMDIconButton>
tooltip_text : 'Edit Bio'
id: edit_profile_pic2
icon: "pencil"
disabled: False #False
pos_hint: {'center_x':0.91,'center_y':0.585}
user_font_size: "25sp"
#on_release: app.file_manager_open()
MDToolbar:
pos_hint: {'top': 1}
md_bg_color: [1,1,1,.3] #if you need a fully transparent Toolbar use [0,0,0,0]
FloatLayout:
BoxLayout:
pos_hint: {'center_x': -.5,'center_y':0.2}
MDIconButton:
icon: 'arrow-left'
pos_hint: {'center_x':0.03,'center_y':0.97}
user_font_size: "25sp"
theme_text_color : 'Custom'
text_color : 0,0,0,1
on_release :
app.goto("navigator") #root.ids.manager.current = 'navigator' #you should have another screen called navigator
#root.ids.manager.transition.direction = 'right'
print(1111)
MDIconButton:
icon: 'home'
pos_hint: {'center_x':0.1,'center_y':0.97}
user_font_size: "25sp"
theme_text_color : 'Custom'
text_color : 0,0,0,1
on_release :
app.goto("home")
#root.manager.current = 'home' #you should have another screen called home
#this does not work root.manager.transition.direction = 'right'
print(2222)
FloatLayout:
BoxLayout:
pos_hint: {'center_x':1.2,'center_y':0.3}
TooltipMDIconButton: #kivy.factory.FactoryException: Unknown class <TooltipMDIconButton>
tooltip_text : 'Edit Cover Picture'
id: edit_cover_pic
icon: "image-edit-outline"
disabled: False
pos_hint: {'center_x':0.03,'center_y':0.97}
user_font_size: "25sp"
on_release: app.file_manager_open_for_cover()
<TooltipMDIconButton@MDIconButton+MDTooltip>
<ScreenB>:
name: "home"
MDToolbar:
pos_hint: {'top': 1}
title: "Home Screen"
left_action_items: [['arrow-left', lambda x: app.goto("studio")]]
#md_bg_color: [1,0,1,.3] #if you need a fully transparent Toolbar use [0,0,0,0]
<ScreenC>:
name: "navigator"
MDToolbar:
pos_hint: {'top': 1}
title: "Navigator Screen"
left_action_items: [['arrow-left', lambda x: app.goto("studio")]]
#md_bg_color: [1,0,1,.3] #if you need a fully transparent Toolbar use [0,0,0,0]
'''
from kivymd.uix.button import MDIconButton
from kivymd.uix.tooltip import MDTooltip
class TooltipMDIconButton(MDIconButton, MDTooltip):
pass
class ScreenB(Screen):
pass
class ScreenC(Screen):
pass
class ProfilePicture(FitImage):
newpic=StringProperty()
#jbsidis
import os
from kivy.clock import Clock
class Example(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Window.bind(on_keyboard=self.events)
self.manager_open = False
self.image_is_profile_or_cover="none"
def goto(self,name_of_the_screen):
self.root.ids.manager.current = name_of_the_screen #'navigator'
def nn(self):
self.file_manager = MDFileManager()
self.file_manager.exit_manager=self.exit_manager
self.file_manager.select_path=self.select_path
## This error is bacause in your own example, the ID of the widgets are different or they must
## be accessed in a different way
## self.root.ids.n1.disabled=False
## File "kivy/properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
## AttributeError: 'super' object has no attribute '__getattr__'
##the id "n1" doesnot exists in the kivy Lang section, so we should specify which one is it
##the id "edit_profile_pic" does exists in the kivy Lang section
#BAD ===== self.root.ids.n1.disabled=False
#GOOD
self.root.ids.edit_profile_pic.disabled=False
self.root.ids.edit_cover_pic.disabled=False
#preview=False
#if you will be using a lot of screens add all of them by doing this
#This must be executed once only, at the beginning
self.root.ids.manager.add_widget(ScreenB())
self.root.ids.manager.add_widget(ScreenC())
def build(self):
image_is_profile_or_cover="none"
Clock.schedule_once(lambda x: self.nn(),3)
return Builder.load_string(KV)
def chpic(self,new):
if os.path.isfile(new)==True:
if self.image_is_profile_or_cover=="cover":
self.root.ids.cover_pic.source=new
print("The picture on 'id: cover_pic' was changed to:",self.root.ids.cover_pic.source)
if self.image_is_profile_or_cover=="profile":
self.root.ids.profile_pic.source=new
print("The picture on 'id: profile_pic' was changed to:",self.root.ids.profile_pic.source)
def file_manager_open_for_profile(self):
self.image_is_profile_or_cover="profile"
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def file_manager_open_for_cover(self):
self.image_is_profile_or_cover="cover"
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def select_path(self, path):
self.exit_manager()
print(path)
if os.path.isfile(path)==True:
Clock.schedule_once(lambda x:self.chpic(path),1)
#toast(path) #here the location for the image file will be returned
return path
def exit_manager(self, *args):
self.manager_open = False
self.file_manager.close()
def events(self, instance, keyboard, keycode, text, modifiers):
if keyboard in (1001, 27):
if self.manager_open:
self.file_manager.back()
return True
Example().run()
So, here is the image: jbsidis (Greetings from El Salvador)