我尝试创建一个简单的计数应用程序。 我有按钮和标签,它们是通过for循环创建的。 按下按钮后,相应的标签应更新为新值(在当前编号上加一个)。
这是.py文件的相应部分:
class ScreenCounter(Screen):
numberButtons = 0
def on_enter(self):
for i in range(len(birdname)):
self.image = Image(source=birdimage[i])
buttonName = 'bird'+str(i)
self.button = Button(id=buttonName,text=birdname[i],on_press=self.onClick)
labelName='birdCount'+str(i)
self.label = Label(id=labelName, text='0')
self.ids.grid.add_widget(self.image)
self.ids.grid.add_widget(self.button)
self.ids.grid.add_widget(self.label)
self.numberButtons += 1
def addCounter(self):
layout = GridLayout(cols = 1, padding = 10)
self.popupLabel = TextInput(text = "", size_hint = [1, .7])
saveButton = Button(text = "Speichern", size_hint = [1, .2])
closeButton = Button(text = "Ende", size_hint = [1, .2])
layout.add_widget(self.popupLabel)
layout.add_widget(saveButton)
layout.add_widget(closeButton)
popup = Popup(title ='Vogelname eingeben',
content = layout,
size_hint = (0.7, 0.4),
pos_hint = {'center_x': 0.5,'center_y': 0.5})
popup.open()
saveButton.bind(on_press = self.save, on_release = popup.dismiss)
closeButton.bind(on_press = popup.dismiss)
def save(self, *args):
buttonName = 'bird'+str(self.numberButtons)
self.button = Button(id=buttonName,text=str(self.popupLabel.text),on_press=self.onClick)
labelName='birdCount'+str(self.numberButtons)
self.label = Label(id=labelName, text='0')
self.ids.grid.add_widget(Label(text=''))
self.ids.grid.add_widget(self.button)
self.ids.grid.add_widget(self.label)
self.numberButtons += 1
def onClick(self, instance):
print(int(instance.id[4:]))
labelNumber = int(instance.id[4:])
labelName = 'birdCount'+str(labelNumber)
print(labelName)
self.ids.grid.ids.labelName.text = 'new'
.kv部分如下所示:
<ScreenCounter>:
canvas.before:
Color:
rgba: 1, 1, 1, 0.3
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation : 'vertical'
Button:
id: newCounter
text: "Neuer Zähler"
background_color : 1, 0, 0, 1
font_size: 80
size_hint: 1, .1
on_press:
root.addCounter()
GridLayout:
orientation: 'horizontal'
id: grid
cols: 3
spacing: 5
padding: 5
主要问题是,我无法更改相应标签的文本,因为我无法解决它。如果我尝试解决例如ID为“ newCounter”的按钮,但是由于标签是在GridLayout的“网格”中创建的,因此似乎失败了。我收到以下错误:
Traceback (most recent call last):
File "kivy/properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
KeyError: 'labelName'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/jeff/python/birdcount/main.py", line 113, in <module>
MyApp().run()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/app.py", line 855, in run
runTouchApp()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 747, in mainloop
self._mainloop()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 479, in _mainloop
EventLoop.idle()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 342, in idle
self.dispatch_input()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 327, in dispatch_input
post_dispatch_input(*pop(0))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 233, in post_dispatch_input
listener.dispatch('on_motion', etype, me)
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/__init__.py", line 1402, in on_motion
self.dispatch('on_touch_down', me)
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/__init__.py", line 1418, in on_touch_down
if w.dispatch('on_touch_down', touch):
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/screenmanager.py", line 1191, in on_touch_down
return super(ScreenManager, self).on_touch_down(touch)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
if child.dispatch('on_touch_down', touch):
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/relativelayout.py", line 288, in on_touch_down
ret = super(RelativeLayout, self).on_touch_down(touch)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
if child.dispatch('on_touch_down', touch):
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
if child.dispatch('on_touch_down', touch):
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
if child.dispatch('on_touch_down', touch):
File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/behaviors/button.py", line 151, in on_touch_down
self.dispatch('on_press')
File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
File "kivy/_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
File "/Users/jeff/python/birdcount/main.py", line 84, in onClick
self.ids.grid.ids.labelName.text = 'new'
File "kivy/properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
这是我的第一篇文章,所以不确定我是否提供所有必要的信息。 另外,我是kivy / python的新手,这是我的第一个“边做边学”应用程序,因此,如果您有改进建议,我很高兴阅读它们。
现在谢谢!
编辑:
这是一个可行的最小示例:
# bird_count - main.py
import kivy
import os
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
counterKV = Builder.load_file("counter.kv")
birdname = ['Amsel', 'Drossel','Buchfink']
class ScreenMain(Screen):
pass
class ScreenCounter(Screen):
numberButtons = 0
def on_enter(self):
for i in range(len(birdname)):
buttonName = 'bird'+str(i)
self.button = Button(id=buttonName,text=birdname[i],on_press=self.onClick)
labelName='birdCount'+str(i)
self.label = Label(id=labelName, text='0')
self.ids.grid.add_widget(self.button)
self.ids.grid.add_widget(self.label)
self.numberButtons += 1
def onClick(self, instance):
pass
# here, the corresponding label should add 1 whenever the button is pressed
#self.ids.grid.ids.labelID.text = int(labelID.text)+1
class Manager(ScreenManager):
pass
class MyApp(App):
def build(self):
return Manager()
if __name__ == '__main__':
MyApp().run()
.kv:
<Manager>:
ScreenMain:
name: 'ScreenMain'
ScreenCounter:
name: 'ScreenCounter'
<ScreenMain>:
BoxLayout:
Button:
text: "Neue Zählung"
background_color : 0.12, 0.42, 0.23, 1
on_press:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0.3
root.manager.current = 'ScreenCounter'
<ScreenCounter>:
BoxLayout:
GridLayout:
orientation: 'horizontal'
id: grid
cols: 3
spacing: 5
padding: 5
我无法删除第一个屏幕,或者遇到其他错误:-|
答案 0 :(得分:0)
加载ids
文件/字符串时,将创建kv
字典。您在id
之外创建的任何kv
都只是Widget
的属性,不会在ids
中。因此,您需要为自己创建一种方法来维护对标签的引用。一种简单的方法是仅保留它们的列表。这是ScreenCounter
类的修改版本(来自mcve
),我认为可以满足您的要求:
class ScreenCounter(Screen):
numberButtons = 0
def __init__(self, **kwargs):
super(ScreenCounter, self).__init__(**kwargs)
self.labels = [] # create a list of labels
def on_enter(self):
for i in range(len(birdname)):
buttonName = 'bird'+str(i)
self.button = Button(id=buttonName,text=birdname[i],on_press=self.onClick)
labelName='birdCount'+str(i)
self.label = Label(id=labelName, text='0')
self.labels.append(self.label) # add this label to the list of labels
self.ids.grid.add_widget(self.button)
self.ids.grid.add_widget(self.label)
self.numberButtons += 1
def onClick(self, instance):
labelNumber = int(instance.id[4:])
# Access the label via the list
self.labels[labelNumber].text = str(int(self.labels[labelNumber].text) + 1)
另一种可能性是创建自己的id
字典。这是ScreenCounter
的另一个版本,使用名为myIds
的字典:
class ScreenCounter(Screen):
numberButtons = 0
def __init__(self, **kwargs):
super(ScreenCounter, self).__init__(**kwargs)
self.myIds = {} # create a dictionary of labels
def on_enter(self):
for i in range(len(birdname)):
buttonName = 'bird'+str(i)
self.button = Button(id=buttonName,text=birdname[i],on_press=self.onClick)
labelName='birdCount'+str(i)
self.label = Label(id=labelName, text='0')
self.myIds[labelName] = self.label # add this label to the myIds dictionary
self.ids.grid.add_widget(self.button)
self.ids.grid.add_widget(self.label)
self.numberButtons += 1
def onClick(self, instance):
labelNumber = int(instance.id[4:])
labelName = 'birdCount'+str(labelNumber)
# Access the label via myIds
self.myIds[labelName].text = str(int(self.myIds[labelName].text) + 1)