![](/img/trans.png)
[英]How to display variable value from Python in KV file in kivy app
[英]kivy error from using a variable from python file to kv file
我正在制作一个 Manga 阅读器,它使用 kivy 中的 Images 模块,我发现了一个可以通过使用从 py 文件到 kv 文件的变量来解决的错误。 我在 App 类中有一个名为sourceToImage
的变量,但是当我在 kv 文件source: app.sourceToImage
调用sourceToImage
变量时source: app.sourceToImage
给了我一个很长的错误
py
class MyApp(App):
sourceToImage = "Source"
def build(self):
return sm
千伏
<ReaderApp>:
name: "reader"
im: page
canvas:
Color:
rgba: 1,1,1,0.17
Rectangle:
size: (root.width, root.height)
pos: (0,0)
Image:
size: 500, 600
pos: 0, 0
id: page
source: app.sourceToImage
但是当我使用app.sourceToImage
它给了我一个错误说:
Traceback (most recent call last):
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 242, in create_handler
return eval(value, idmap), bound_list
File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20, in <module>
source: app.sourceToImage
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app
app.bind(on_stop=lambda instance:
AttributeError: 'NoneType' object has no attribute 'bind'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 695, in _apply_rule
value, bound = create_handler(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 245, in create_handler
raise BuilderException(rule.ctx, rule.line,
kivy.lang.builder.BuilderException: Parser: File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20:
...
18: pos: 0, 0
19: id: page
>> 20: source: app.sourceToImage
21:
22:
...
AttributeError: 'NoneType' object has no attribute 'bind'
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 242, in create_handler
return eval(value, idmap), bound_list
File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20, in <module>
source: app.sourceToImage
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app
app.bind(on_stop=lambda instance:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\main.py", line 87, in <module>
kv = Builder.load_file("my.kv")
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 306, in load_file
return self.load_string(data, **kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 408, in load_string
self._apply_rule(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 661, in _apply_rule
child.apply_class_lang_rules(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\uix\widget.py", line 463, in apply_class_lang_rules
Builder.apply(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 541, in apply
self._apply_rule(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 710, in _apply_rule
raise BuilderException(rule.ctx, rule.line,
kivy.lang.builder.BuilderException: Parser: File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20:
...
18: pos: 0, 0
19: id: page
>> 20: source: app.sourceToImage
21:
22:
...
BuilderException: Parser: File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20:
...
18: pos: 0, 0
19: id: page
>> 20: source: app.sourceToImage
21:
22:
...
AttributeError: 'NoneType' object has no attribute 'bind'
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 242, in create_handler
return eval(value, idmap), bound_list
File "D:\GameDev-Programming\Python\kivyProjects\firstKivy\my.kv", line 20, in <module>
source: app.sourceToImage
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app
app.bind(on_stop=lambda instance:
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 695, in _apply_rule
value, bound = create_handler(
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 245, in create_handler
raise BuilderException(rule.ctx, rule.line,
完整的kv文件:
WindowManager:
SelectingApp:
ReaderApp:
<ReaderApp>:
name: "reader"
im: page
canvas:
Color:
rgba: 1,1,1,0.17
Rectangle:
size: (root.width, root.height)
pos: (0,0)
Image:
size: 500, 600
pos: 0, 0
id: page
source: ""
<SelectingApp>
name: "selecting"
listSpin: spinnerId
canvas:
Color:
rgba: 1,1,1,0.17
Rectangle:
size: (root.width, root.height)
pos: (0,0)
FloatLayout:
Label:
text: app.sourceToImage
size_hint: 0.1,0.1
pos_hint: {"x": 0.4, "y": 0.5}
Button:
text: "Go to reader"
on_press: root.Change()
size_hint: 0.5, 0.05
pos_hint: {"x": 0.2}
Spinner:
id: spinnerId
text: "Choose Manga"
values: ["hey", "ey"]
size_hint: 0.3, 0.1
pos_hint: {"x":0.3, "y":0.4}
Button:
text: "refresh list"
size_hint: 0.5, 0.05
pos_hint: {"x": 0.2, "y": 0.2}
on_press: root.Refresh()
完整的py文件:
import os
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.config import Config
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
width = 360
height = 640 # How does this make the resolution 641
Config.set('graphics', 'width', width)
Config.set('graphics', 'height', height)
Manga = "Seirei Gensouki - Konna Sekai De Deaeta Kimi Ni"
page = 0
arr = os.listdir(f"Manga/{Manga}")
MangaList = os.listdir("Manga")
fileCount = len(arr)
class WindowManager(ScreenManager):
pass
class ReaderApp(Screen):
im = ObjectProperty(None)
def NextPage(self):
global page
if fileCount > page:
page += 1
if arr[0] == "1.jpg":
self.im.source = f"Manga/{Manga}/{page}.jpg"
else:
self.im.source = f"Manga/{Manga}/{page}.png"
print("next page")
def PreviousPage(self):
global page
if page > 1:
page -= 1
if arr[0] == "1.jpg":
self.im.source = f"Manga/{Manga}/{page}.jpg"
else:
self.im.source = f"Manga/{Manga}/{page}.png"
print("previous page")
def on_touch_down(self, touch):
global page
xPos, yPos, = touch.pos
xPos = int(xPos)
yPos = int(yPos)
print(f"X: {xPos}\nY: {yPos}")
if xPos > 300 and yPos > 600:
sm.current = "selecting"
f = open("Records", "r+")
f.writelines(f"{Manga};{page}")
f.close()
elif self.width * .30 > xPos:
self.PreviousPage()
elif xPos > self.width * .70:
self.NextPage()
class SelectingApp(Screen):
listSpin = ObjectProperty(None)
def Refresh(self):
self.listSpin.values = MangaList
def Change(self):
global page
f = open("Records", "r")
records = f.read().split("\n")
print(records)
for lines in records:
print(lines)
mangaTitle, mangaPage = lines.split(";")
print(mangaTitle, mangaPage)
if mangaTitle == Manga:
page = int(mangaPage)
sm.current = "reader"
kv = Builder.load_file("my.kv")
sm = WindowManager()
screens = [SelectingApp(name="selecting"), ReaderApp(name="reader")]
for screen in screens:
sm.add_widget(screen)
class MyApp(App):
sourceToImage = StringProperty(f"Manga/{Manga}/{page}.jpg")
def build(self):
return sm
if __name__ == "__main__":
MyApp().run()
您的代码有几个问题:
您的kv
代码引用app
,但kv
在创建App
之前加载。 这就是为什么您会收到有关NoneType
的消息(此时app
为None
)。 您可以通过在App
的build()
方法中移动kv = Builder.load_file("my.kv")
来解决这个问题。 但请参阅以下注意事项。
您正在构建App
小部件树两次。 一次使用kv = Builder.load_file("my.kv")
,再次使用代码:
sm = WindowManager() screens = [SelectingApp(name="selecting"), ReaderApp(name="reader")] for screen in screens: sm.add_widget(screen)
您可以消除上述代码和Builder.load_file()
代码。 见下文。
kv
文件命名为my.kv
,它将由 kivy 自动加载,因此您不需要上述任何一种技术来构建App
小部件树。 所以你的App
类可以很简单:
class MyApp(App):
sourceToImage = StringProperty(f"Manga/{Manga}/{page}.jpg")
根本没有build()
方法。 然后,在您引用sm.current
的方法中,您可以使用self.manager.current
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.