問題描述
作為后續問題:
- Kivy 外部規則繼承
- 使用 add_widget() 繼承 Kivy 規則李>
main.py
import os
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.properties import ObjectProperty
class FancyButton(Button):
imp = ObjectProperty(None)
class Important(StackLayout):
font_kanji = os.path.join('fonts', 'TakaoPMincho.ttf')
def NoInspiration(self, smile):
print("Received: {}".format(smile))
def AddFancy(self):
print(self.ids)
temp = FancyButton(text='f', imp = self)
self.ids.boxy.add_widget(temp)
class TestApp(App):
def build(self):
pass
if __name__ == '__main__':
TestApp().run()
test.kv
#:kivy 1.9.0
<FancyButton>:
font_name: self.imp.font_kanji # ERROR
on_release: self.imp.NoInspiration(':)') # WORKS
<Important>:
id: imp
BoxLayout:
id: boxy
orientation: 'vertical'
FancyButton:
text: "smiley"
imp: root
Button:
text: "add fancy"
on_release: imp.AddFancy()
BoxLayout:
Important
在上面的示例中,'on_release: self.imp.NoInspiration(':)')' 有效,因為 FancyButton 具有 'imp: root'.
In the above example 'on_release: self.imp.NoInspiration(':)')' works because FancyButton has 'imp: root'.
但是 'font_name: self.imp.font_kanji' 不起作用并給出錯誤:
However 'font_name: self.imp.font_kanji' doesn't work and gives the error:
AttributeError: 'NoneType' 對象沒有屬性 'font_kanji'
AttributeError: 'NoneType' object has no attribute 'font_kanji'
我的猜測是這樣做的原因是 on_release 發生在所有小部件都直接加載和 font_name 之后,所以沒有'imp:root'.
My guess is the reason for this is that on_release takes place after all widgets are loaded and font_name directly, so without having 'imp: root'.
我也試過了:
font_kanji = StringProperty(os.path.join('fonts', 'TakaoPMincho.ttf'))
,但無濟于事.
如何讓 font_name 引用 font_kanji?我應該使用全局嗎?如果是,您將如何在 Python 中設置可以在 .kv 中訪問的全局?
How do I get font_name refer to font_kanji? Should I use global? If yes, how would you set a global in Python which can be accessed in the .kv?
(如果我將 global 放在 font_Kanji 前面并刪除 .kv 文件中的 'self.imp' 我會收到錯誤:NameError: name 'font_kanji' is not defined")
(If I put global in front of font_Kanji and remove 'self.imp' in the .kv file I get the error: " NameError: name 'font_kanji' is not defined")
推薦答案
你的猜測是正確的:當你的按鈕被創建時,它的 imp
屬性是 None
.解決這個問題的方法是觀察 imp
屬性并在其處理程序中設置 font_name
的值:
Your guess is right: when your button is created its imp
property is None
. One to go around this would be to observe imp
property and set the value of font_name
in its handler:
class FancyButton(Button):
imp = ObjectProperty(None)
def on_imp(self, obj, imp):
if imp:
self.font_name = imp.font_kanji
這樣字體是在 imp
屬性用適當的 Important
實例初始化之后設置的.這種方法的缺點是Instance.font_kanji
的變化不會觸發FancyButton.font_name
的變化.
This way the font is set after imp
property is initialzied with proper Important
instance. The dissadvantage of this method is that changes of Instance.font_kanji
won't trigger changes of FancyButton.font_name
.
如果你想綁定兩個屬性,那么你必須從 Instance.font_kanji
端調用 bind
函數(因為我們想對其更改做出反應)以動態創建 FancyButton
實例:
If you want to have both properties binded, then you have to call bind
funtion from Instance.font_kanji
side (since we want to react to its changes) for dynamically created FancyButton
instances:
class Important(StackLayout):
font_kanji = os.path.join('fonts', 'TakaoPMincho.ttf')
def NoInspiration(self, smile):
print("Received: {}".format(smile))
def AddFancy(self):
temp = FancyButton(text='f', imp = self)
self.bind(font_kanji=temp.setter('font_name'))
self.ids.boxy.add_widget(temp)
kv語言定義的接口可以直接綁定:
Interface defined in the kv language can do the binding directly:
<Important>:
id: imp
BoxLayout:
id: boxy
orientation: 'vertical'
FancyButton:
text: "smiley"
font_name: root.font_kanji
imp: root
Button:
text: "add fancy"
on_release: imp.AddFancy()
''')
這篇關于Kivy 外部規則繼承 2的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!