在 KivyMD 上的小部件之间添加数值
Posted
技术标签:
【中文标题】在 KivyMD 上的小部件之间添加数值【英文标题】:Adding numerical values among widgets on KivyMD 【发布时间】:2021-01-18 07:56:32 【问题描述】:我正在构建一个作为差旅费用经理的应用程序。我目前正在尝试构建一个系统,您可以在其中将请求的金额插入 MDTextField 并按下按钮以确认请求。同时,在其他小部件上,我想将请求的总金额加起来。
即如果我在 TextField 上写 1000 并单击按钮“Ingresar Gasto”,则标签“MONTO TOTAL SOLICITADO”下方的值应该会更新,并且目标 MDTextField 和具有原始编号的 MDTextField 都应该具有正确格式的 $1,000.00。
对于我拥有相同小部件的所有扩展面板来说,同样的需要也是如此。
我尝试了以下方法:
扩展面板的Kivy代码:
<MyContentAliment>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_aliment_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_aliment_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.sumar_gasto()
MDCard 的 Kivy 代码(包含目标小部件):
<TravelManagerWindow>:
BoxLayout:
size_hint:1,0.85
pos_hint: "center_x": 0.5, "center_y":0.37
adaptive_height:True
height: self.minimum_height
ScrollView:
adaptive_height:True
GridLayout:
id: container
size_hint_y: None
cols: 1
row_default_height: root.height*0.10
height: self.minimum_height
MDBoxLayout:
adaptive_height: True
orientation: 'horizontal'
GridLayout:
id: panel_container
size_hint_x: 0.6
cols: 1
adaptive_height: True
MDBoxLayout:
size_hint_x: 0.05
MDCard:
id: resumen_solicitud
size_hint: None, None
size: "250dp", "300dp"
pos_hint: "top": 0.9, "center_x": .5
elevation: 0.1
MDBoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgba: 0.8, 0.8, 0.8, 1
Rectangle:
pos: self.pos
size: self.size
MDLabel:
text: 'Monto Total Solicitado'
font_style: 'Button'
halign: 'center'
font_size: (root.width**2 + root.height**2) / 15.5**4
size_hint_y: 0.2
MDSeparator:
height: "1dp"
MDTextField:
id: suma_solic_viaje
text: "$ 0.00"
bold: True
line_color_normal: app.theme_cls.primary_color
halign: "center"
size_hint_x: 0.8
最后但同样重要的是,Python 代码:
class TravelManagerWindow(Screen):
viajeInicio = ObjectProperty(None)
panel_container = ObjectProperty(None)
travel_list = ObjectProperty(None)
DateMDTextField = ObjectProperty(None)
menu = ObjectProperty()
# EXPANSION PANEL PARA SOLICITAR GV
def set_expansion_panel(self):
#FOOD PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food.png",
content=MyContentAliment(),
panel_cls=MDExpansionPanelOneLine(
text="Alimentacion")))
# CASETAS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(
icon="casetas.png",
content=MyContentCasetas(),
panel_cls=MDExpansionPanelOneLine(
text="Casetas")))
# GAS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="gas.png",
content=MyContentGasolina(),
panel_cls=MDExpansionPanelOneLine(
text="Gasolina")))
# HOSPEDAJE PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(
icon="hospedaje.png", content=MyContentHosped(),
panel_cls=MDExpansionPanelOneLine(
text="Hospedaje")))
# VARios PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(
icon="varios.png", content=MyContentVarios(),
panel_cls=MDExpansionPanelOneLine(
text="Varios")))
所有面板容器都有相同的代码,仅引用不同的 小部件(为简单起见未添加)
class MyContentAliment(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_aliment_viaje.text) <= 3 and
(self.ids.monto_aliment_viaje.text).isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_aliment_viaje.text) == 4 and
(self.ids.monto_aliment_viaje.text).isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[0] + "," + \
self.ids.monto_aliment_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_aliment_viaje.text) == 5 and
(self.ids.monto_aliment_viaje.text).isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[:2] + "," + \
self.ids.monto_aliment_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_aliment_viaje.text) > 5 and
self.ids.monto_aliment_viaje.text.startswith('$') == False:
self.ids.monto_aliment_viaje.text = self.ids.monto_aliment_viaje.text[:-1]
def sumar_gasto(self):
if self.ids.monto_aliment_viaje.text == "":
pass
else:
travel_manager = TravelManagerWindow()
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
monto_total += float(self.ids.monto_aliment_viaje.text)
travel_manager.ids.suma_solic_viaje.text= "$ " + str(monto_total)
self.apply_currency_format()
### WINDOW MANAGER ################################
class WindowManager(ScreenManager):
pass
ScreenManager().add_widget(LoginWindow(name='login'))
ScreenManager().add_widget(CreateAccountWindow(name='create'))
ScreenManager().add_widget(MainWindow(name='main'))
ScreenManager().add_widget(IngActivWindow(name='ingActiv'))
ScreenManager().add_widget(CronogramaWindow(name='cronograma'))
ScreenManager().add_widget(TravelManagerWindow(name='travelManager'))
ScreenManager().add_widget(SoporteTecnicoWindow(name='soporteTecnico'))
class powerApp2(MDApp):
pass
if __name__ == "__main__":
powerApp2().run()
由于 apply_currency_format 函数,目前我得到了正确的格式。然而,当我按下按钮时,目标文本字段的值保持不变。
非常感谢。
最小可重复示例的代码:
Python 代码:
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelOneLine
from kivy.uix.boxlayout import BoxLayout
class MyContentAliment(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_aliment_viaje.text) <= 3 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_aliment_viaje.text) == 4 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[0] + "," + \
self.ids.monto_aliment_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_aliment_viaje.text) == 5 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[:2] + "," + \
self.ids.monto_aliment_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_aliment_viaje.text) > 5 and self.ids.monto_aliment_viaje.text.startswith('$') == False:
self.ids.monto_aliment_viaje.text = self.ids.monto_aliment_viaje.text[:-1]
def sumar_gasto(self):
if self.ids.monto_aliment_viaje.text == "":
pass
else:
travel_manager = TravelManagerWindow()
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
monto_total += float(self.ids.monto_aliment_viaje.text)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.apply_currency_format()
class MyContentCasetas(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_casetas_viaje.text) <= 3 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_casetas_viaje.text) == 4 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text[0] + "," + \
self.ids.monto_casetas_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_casetas_viaje.text) == 5 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text[:2] + "," + \
self.ids.monto_casetas_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_casetas_viaje.text) > 5 and self.ids.monto_casetas_viaje.text.startswith('$') == False:
self.ids.monto_casetas_viaje.text = self.ids.monto_casetas_viaje.text[:-1]
class MyContentGasolina(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_gas_viaje.text) <= 3 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_gas_viaje.text) == 4 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text[0] + "," + \
self.ids.monto_gas_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_gas_viaje.text) == 5 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text[:2] + "," + \
self.ids.monto_gas_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_gas_viaje.text) > 5 and self.ids.monto_gas_viaje.text.startswith('$') == False:
self.ids.monto_gas_viaje.text = self.ids.monto_gas_viaje.text[:-1]
class MyContentHosped(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_hosped_viaje.text) <= 3 and self.ids.monto_hosped_viaje.text.isnumeric():
self.ids.monto_hosped_viaje.text = "$" + self.ids.monto_hosped_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_hosped_viaje.text) == 4 and self.ids.monto_hosped_viaje.text.isnumeric():
self.ids.monto_hosped_viaje.text = "$" + self.ids.monto_hosped_viaje.text[0] + "," + \
self.ids.monto_hosped_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_hosped_viaje.text) == 5 and self.ids.monto_hosped_viaje.text.isnumeric():
self.ids.monto_hosped_viaje.text = "$" + self.ids.monto_hosped_viaje.text[:2] + "," + \
self.ids.monto_hosped_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_hosped_viaje.text) > 5 and self.ids.monto_hosped_viaje.text.startswith('$') == False:
self.ids.monto_hosped_viaje.text = self.ids.monto_hosped_viaje.text[:-1]
class MyContentVarios(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_varios_viaje.text) <= 3 and self.ids.monto_varios_viaje.text.isnumeric():
self.ids.monto_varios_viaje.text = "$" + self.ids.monto_varios_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_varios_viaje.text) == 4 and self.ids.monto_varios_viaje.text.isnumeric():
self.ids.monto_varios_viaje.text = "$" + self.ids.monto_varios_viaje.text[0] + "," + \
self.ids.monto_varios_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_varios_viaje.text) == 5 and self.ids.monto_varios_viaje.text.isnumeric():
self.ids.monto_varios_viaje.text = "$" + self.ids.monto_varios_viaje.text[:2] + "," + \
self.ids.monto_varios_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_varios_viaje.text) > 5 and self.ids.monto_varios_viaje.text.startswith('$') == False:
self.ids.monto_varios_viaje.text = self.ids.monto_varios_viaje.text[:-1]
class LoginWindow(Screen):
pass
class TravelManagerWindow(Screen):
panel_container = ObjectProperty(None)
# EXPANSION PANEL PARA SOLICITAR GV
def set_expansion_panel(self):
# FOOD PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentAliment(),
panel_cls=MDExpansionPanelOneLine(text="Alimentacion")))
# CASETAS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentCasetas(),
panel_cls=MDExpansionPanelOneLine(text="Casetas")))
# GAS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentGasolina(),
panel_cls=MDExpansionPanelOneLine(text="Gasolina")))
# HOSPEDAJE PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentHosped(),
panel_cls=MDExpansionPanelOneLine(text="Hospedaje")))
# VARIOS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentVarios(),
panel_cls=MDExpansionPanelOneLine(text="Varios")))
### WINDOW MANAGER ################################
class WindowManager(ScreenManager):
pass
ScreenManager().add_widget(LoginWindow(name='login'))
ScreenManager().add_widget(TravelManagerWindow(name='travelManager'))
class reprodExample(MDApp):
def build(self):
self.theme_cls.primary_palette = "Teal"
return WindowManager()
if __name__ == "__main__":
reprodExample().run()
KV 文件代码:
<WindowManager>:
LoginWindow:
TravelManagerWindow:
<LoginWindow>:
MDRaisedButton:
text: 'Enter'
pos_hint: 'center_x': 0.5, 'center_y': 0.5
size_hint: None, None
on_release:
root.manager.transition.direction = 'up'
root.manager.current = 'travelManager'
<TravelManagerWindow>:
name:'travelManager'
on_pre_enter: root.set_expansion_panel()
BoxLayout:
orientation: 'vertical'
size_hint:1,0.85
pos_hint: "center_x": 0.5, "center_y":0.37
adaptive_height:True
height: self.minimum_height
ScrollView:
adaptive_height:True
GridLayout:
size_hint_y: None
cols: 1
row_default_height: root.height*0.10
height: self.minimum_height
BoxLayout:
adaptive_height: True
orientation: 'horizontal'
GridLayout:
id: panel_container
size_hint_x: 0.6
cols: 1
adaptive_height: True
BoxLayout:
size_hint_x: 0.05
MDCard:
id: resumen_solicitud
size_hint: None, None
size: "250dp", "300dp"
pos_hint: "top": 0.9, "center_x": .5
elevation: 0.1
MDBoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgba: 0.8, 0.8, 0.8, 1
Rectangle:
pos: self.pos
size: self.size
MDLabel:
text: 'Monto Total Solicitado'
font_style: 'Button'
halign: 'center'
font_size: (root.width**2 + root.height**2) / 15.5**4
size_hint_y: 0.2
MDSeparator:
height: "1dp"
MDTextField:
id: suma_solic_viaje
text: "$ 0.00"
bold: True
line_color_normal: app.theme_cls.primary_color
halign: "center"
size_hint_x: 0.8
pos_hint: 'center_x': 0.5, 'center_y': 0.5
MDSeparator:
height: "1dp"
BoxLayout:
id: expense_graph
halign: 'center'
<MyContentAliment>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_aliment_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_aliment_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.sumar_gasto()
### CASETAS
<MyContentCasetas>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_casetas_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
#input_filter: 'float'
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_casetas_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.apply_currency_format()
BoxLayout:
size_hint_x: 0.05
### GASOLINA
<MyContentGasolina>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_gas_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
#input_filter: 'float'
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_gas_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.apply_currency_format()
BoxLayout:
size_hint_x: 0.05
### HOSPEDAJE
<MyContentHosped>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_hosped_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
#input_filter: 'float'
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_hosped_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.apply_currency_format()
BoxLayout:
size_hint_x: 0.05
### VARIOS
<MyContentVarios>:
adaptive_height: True
MDBoxLayout:
orientation:'horizontal'
adaptive_height:True
size_hint_x:self.width
pos_hint: "center_x":0.5, "center_y":0.5
spacing: dp(10)
padding_horizontal: dp(10)
MDLabel:
text: 'Monto:'
multiline: 'True'
halign: 'center'
pos_hint: "x":0, "top":0.5
size_hint_x: 0.15
font_style: 'Button'
font_size: 19
MDTextField:
id: monto_varios_viaje
hint_text: 'Monto a solicitar'
pos_hint: "x":0, "top":0.5
halign: 'left'
size_hint_x: 0.3
helper_text: 'Ingresar el monto a solicitar'
helper_text_mode: 'on_focus'
write_tab: False
#input_filter: 'float'
required: True
on_text:
root.limit_currency()
MDRaisedButton:
id: boton_varios_viaje
pos_hint: "x":0, "top":0.5
text:'Ingresar Gasto'
on_release:
root.apply_currency_format()
BoxLayout:
size_hint_x: 0.05
【问题讨论】:
请发minimal reproducible example。 【参考方案1】:在您的 sumar_gasto()
方法中,该行:
travel_manager = TravelManagerWindow()
正在创建TravelManagerWindow
的新实例,该实例与您的 GUI 中显示的实例无关。因此,您对该实例所做的任何更改都不会影响您的 GUI。
如果没有看到更多您的代码,我无法猜测您如何访问实际在您的 GUI 中的 TravelManagerWindow
实例。
所以,您可以自己解决这个问题,也可以发帖 minimal, complete, verifiable example。
所以,随着附加代码的发布,我认为您可以替换:
travel_manager = TravelManagerWindow()
与:
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
这是因为MDApp
的root
小部件是WindowManager
。
您还应该在kv
中为LoginWindow
添加name
:
<LoginWindow>:
name: 'login'
MDRaisedButton:
text: 'Enter'
pos_hint: 'center_x': 0.5, 'center_y': 0.5
size_hint: None, None
on_release:
root.manager.transition.direction = 'up'
root.manager.current = 'travelManager'
我还注意到你有一些不必要的代码:
ScreenManager().add_widget(LoginWindow(name='login'))
ScreenManager().add_widget(TravelManagerWindow(name='travelManager'))
以上行没有任何效果,原因与travel_manager = TravelManagerWindow()
代码相同。调用ScreenManager()
会创建一个不在您的GUI 中的ScreenManager
的新实例,向该实例添加Widget
不会对您的GUI 产生任何影响。在kv
开头的WindowManager
规则将构建两个Screens
,然后添加到WindowManager
。
【讨论】:
感谢您的回复约翰,我编辑了我的帖子并添加了一个用于最小可重现示例的代码部分。非常感谢提前 约翰你能看看我最近发布的这个新问题吗?这是您帮助我解决的这个老问题的延续。我会分享链接。非常感谢。[***.com/questions/65583656/…以上是关于在 KivyMD 上的小部件之间添加数值的主要内容,如果未能解决你的问题,请参考以下文章