我有两个文件demo.py
和demo.kv
谁能告诉我如何将函数从一个类调用到另一个类?我想从def calculate(self):
调用def on_text(self, text_input, value):
。现在我正在使用代码
def on_text(self, text_input, value):
App.get_running_app().User.calculate()
但是它给出了错误AttributeError:'测试'对象没有属性'用户'
demo.py
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.uix.popup import Popup
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Popup):
total_value = ObjectProperty(None)
def add_more(self):
self.ids.rows.add_row()
def calculate(self):
rows = self.ids.rows
total = 0
for row in rows.children:
text = row.ids.number_input.text
total += int(text) if text != "" else 0 # validate if the entry is not empty
self.total_value.text = str(total)
class Row(BoxLayout):
col_data = ListProperty(["?", "?", "?", "?", "?"])
button_text = StringProperty("")
col_data3 = StringProperty("")
col_data4 = StringProperty("")
def __init__(self, **kwargs):
super(Row, self).__init__(**kwargs)
self.ids.number_input.bind(text=self.on_text)
def on_text(self, text_input, value):
print('Calling')
App.get_running_app().User.calculate()
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class rv(BoxLayout):
data_items = ListProperty([])
mode = StringProperty("")
def __init__(self, **kwargs):
super(rv, self).__init__(**kwargs)
def add(self):
self.mode = "Add"
popup = User()
popup.open()
class MainMenu(BoxLayout):
content_area = ObjectProperty()
def display(self):
self.rv = rv()
self.content_area.add_widget(self.rv)
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return MainMenu()
if __name__ == '__main__':
Test().run()
demo.kv
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
TextInput:
text: root.col_data3
width: 300
TextInput:
id: number_input
text: root.col_data4
width: 300
input_filter: 'int'
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<User>:
id: user
total_value:total_value
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Number"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "name"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "Value"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size: 200, 40
size_hint: None, None
Label:
size_hint_x: .7
text: "Total value"
TextInput:
id: total_value
on_focus:root.test()
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
<rv>:
BoxLayout:
orientation: "vertical"
Button:
size_hint: .25, .03
text: "+Add"
on_press: root.add()
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
BoxLayout:
orientation: "vertical"
<MenuButton@Button>:
text_size: self.size
valign: "middle"
padding_x: 5
size : (100, 40)
size_hint : (None, None)
background_color: 90 , 90, 90, 90
background_normal: ''
color: 0, 0.517, 0.705, 1
border: (0, 10, 0, 0)
<MainMenu>:
content_area: content_area
BoxLayout:
orientation: 'vertical'
spacing : 10
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size_hint_y: 2
MenuButton:
text: 'Menu'
size : (50, 12)
on_release: root.display()
BoxLayout:
id: content_area
size_hint_y: 30
答案 0 :(得分:1)
在不访问kivy层次结构树的情况下解决此问题的一种方法是使用全局变量,但建议不要滥用此类变量,因为其滥用所产生的错误很难跟踪。
[...]
class Row(BoxLayout):
[...]
def on_text(self, text_input, value):
print('Calling')
popup.calculate()
class rv(BoxLayout):
[...]
def add(self):
self.mode = "Add"
global popup
popup = User()
popup.open()
[...]
答案 1 :(得分:1)
这可能与此问题重复:Im New on kivy Python classes
首先:
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return MainMenu()
这有点不必要,你可以改为:
class demo(App):
def build(self):
return MainMenu()
应用程序搜索小写名称等于应用程序名称的kv文件。
其次:
<User>:
id: user
total_value:total_value
这不是你在kivy Widgets中使用id的方式。当您定义Kivy Widget时,即:
class KivyWidgetName(KivyLayout):
pass
<KivyWidgetName>:
您正在创建课程。将自定义窗口小部件添加到父窗口小部件时,您将创建该KivyWidget类的对象。然而,有时候如果你不止一个,你需要给它们id,这样它们的父母就可以将它们彼此分开。
即:
<RootWidget>:
KivyWidgetName:
id: first_instance
KivyWidgetName:
id: second_instance
所以现在RootWidget可以访问该类的两个不同版本,如果它想要访问第一个版本,它可以这样做:
self.ids.first_instance
您也可以通过它们出现的索引号来访问它们,所以这个 也可以通过以下方式完成:
self.ids[1]
然而,显式通常比隐式
更好第三,你对此有正确的想法:
App.get_running_app().User.calculate()
但它应该是这样的:
App.get_running_app().root.ids.[INSERTID]
因此,在这种情况下,您正在获取应用程序的根小部件(即),然后您需要使用ID来获取正确的地址。
例如,拿这个:
: 用户: id:&#39; user_one&#39; 用户: id:&#39; user_two&#39;
要访问用户计算功能,您可以执行以下操作:
App.get_running_app().root.ids.user_one.calculate
如果您有许多孩子,在找到用户之前,您必须寻找他们的所有ID:
例如:
<TestWidget>:
User:
id: 'user_one'
User:
id: 'user_two'
<RootWidget>:
TestWidget:
id: 'test_one'
TestWidget:
id: 'test_two'
因此,要获得测试二的用户之一,您可以这样做:
App.get_running_app()。root.ids.test_two.ids.user_one.calculate
你可能需要重新安排你的rootwidget是一个只包含你的主菜单的东西,以帮助你解决这个问题,但这个决定最终取决于你。