如何编写程序让用户使用按钮将头像添加到 KivyMD 应用程序
Posted
技术标签:
【中文标题】如何编写程序让用户使用按钮将头像添加到 KivyMD 应用程序【英文标题】:How to write a program for the user to add a profile picture to the KivyMD application using the button 【发布时间】:2021-10-17 22:07:07 【问题描述】:我想为用户编写一个程序,以使用按钮将个人资料图片添加到 KivyMD 应用程序。我编写 Python 程序来做到这一点的知识是有限的。请帮帮我。
【问题讨论】:
【参考方案1】:您可以使用 MDFileManager 类打开一个文件浏览器,该浏览器返回您选择的图像的位置,为了使本示例正常工作,请确保您有一个名为“i.jpeg”的图像(您可以在源代码),如果您在保存此 python 脚本的同一目录(同一文件夹)中没有该图像,则此示例将失败:
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()
这个例子来自我 (jbsidis),它有来自 kivymd 文档的部分,但是我改变了很多东西让它工作,如果你只从文档中复制和粘贴 MDFileManager 例子,它可能会失败,那就是为什么在这个例子中你会看到 MDFileManager 类在 3 秒后被定位并执行(这是因为“kivymd 错误”而需要),订阅我在 youtube 中的频道:https://www.youtube.com/channel/UCIMmPyY7XjWHk1AHlR_UdWQ
jbsidis
@jbsidis Josué Carranza - 先生,首先我尝试了您提供的代码 以上,已成功运行。但是当我将它添加到我的代码中时 可以打开文件管理器。但图片无法更改。 出现问题。
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
我认为问题出在我的代码上。但我不明白有什么问题。我该如何解决?
这是我的代码
.kv 文件
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'
我想更换id : profile_pic
和id : cover pic
的图片
.py 文件
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
你能给我一个合适的代码示例
是的,我正在分析您的代码,我将为您的程序提供正确的代码,此外,阅读代码中的所有 cmets,我正在添加注释,以便您可以获得有关错误的更多信息,我个人的建议是,总是做一个单一的python脚本(我的意思是不要把程序分成kv文件和py文件,除非你使用的是HotReloadViewer),所以这里是固定的代码:
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()
所以,这是图像: jbsidis(来自萨尔瓦多的问候)
【讨论】:
非常感谢以上是关于如何编写程序让用户使用按钮将头像添加到 KivyMD 应用程序的主要内容,如果未能解决你的问题,请参考以下文章