問題描述
如何覆蓋 Kivy 小部件子部件的默認值?即
MyWidget.label
是默認",但我想將其更改為例如當MyRootWidget
的孩子時出現紫龜"?
How can I overwrite the default value of a Kivy widget's child? i.e.
MyWidget.label
is 'default' but I want to change it to e.g. 'purple turtle' when a child ofMyRootWidget
?
我可以像在MyRootWidget.__init__()
中那樣訪問children的children,但是看起來很麻煩,尤其是對于一棵很深的樹...有沒有更優雅的怎么辦?
I can access the children of children as I've done in MyRootWidget.__init__()
, but it seems cumbersome, especially for a deep tree ... is there a more elegant way of doing it?
我一直在查看 Kivy lang 和 Widget 頁面,但無法理解是否存在解決方案.我在 SO 頁面中還沒有看到這個問題(盡管在我搜索時確實回答了一個不同的問題).
I've been looking over the Kivy lang and Widget pages, but haven't been able to understand a solution if it's there. I haven't seen quite this issue in SO pages (though the did answer a different question while I was searching).
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, StringProperty
root = Builder.load_string('''
<MyWidget@BoxLayout>:
orientation: 'vertical'
Label:
id: label
text: 'DEFAULT'
<MyRootWidget@BoxLayout>:
id: root_widget
MyWidget:
id: w1
# (---1---)
''')
class MyRootWidget(BoxLayout):
w1 = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print(self.ids.w1.ids.label.text) # (---2---)
class MainApp(App):
def build(self):
return MyRootWidget()
if __name__ == '__main__':
MainApp().run()
推薦答案
首先,在實現任何代碼之前,你必須設計你的類.
First of all, before implementing any code, you must design your classes.
首先我們將使用 MyWidget,在您的要求中表明您希望文本是可修改的,因此它必須是根屬性.
First we will do it with MyWidget, in your requirements you indicate that you want the text to be modifiable so it must be a root property.
MyWidget
┌--------------------------┐
| |
| ┌-------------┐ text---┼--->
| | Label | | |
| | *text ---┼-----┘ |
| └-------------┘ |
└--------------------------┘
MyRootWidget 也可以這樣做:
The same could be done with MyRootWidget:
MyRootWidget
┌-----------------------------┐
| |
| ┌-------------┐ obj_widget--┼--->
| | MyWidget --┼-----┘ |
| | | |
| └-------------┘ |
└-----------------------------┘
屬性的深度取決于您的要求,但如果我們觀察到公開屬性,則意味著在根中創建屬性并進行綁定,以便在修改根屬性時也會修改內部屬性.
The depth of the property depends on your requirements, but if we observe exposing a property it implies creating a property in the root and making a binding so that when the root property is modified the internal property is modified as well.
實現上述你會得到以下結果:
Implementing the above you get the following:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, StringProperty
root = Builder.load_string('''
<MyWidget@BoxLayout>:
text: "DEFAULT"
obj_label: label
orientation: 'vertical'
Label:
id: label
text: root.text
<MyRootWidget@BoxLayout>:
obj_widget: w1
MyWidget:
id: w1
text: "purple turtle"
''')
class MyRootWidget(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
print(self.obj_widget.text)
class MainApp(App):
def build(self):
return MyRootWidget()
if __name__ == '__main__':
MainApp().run()
因此,為了避免 id,您可以為子小部件創建一個別名,就像我對 obj_widget 所做的那樣,它是 w1 的別名.
So to avoid the ids you can create an alias to the children widget like I did with obj_widget which is an alias of w1.
按照設計,您不應該直接訪問完整的樹,但您必須修改層的屬性,如果修改了該層,則必須更新其內部的必要數據,以避免類之間的耦合.
By design you should not access the complete tree directly but you must modify the property of a layer and this layer if it is modified then you must update the necessary data in its internal part so we avoid the coupling between classes.
這篇關于在 kivy lang 和 python 中訪問子小部件屬性的值的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!