繁体   English   中英

使用python文件中的变量到kv文件的kivy错误

[英]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的消息(此时appNone )。 您可以通过在Appbuild()方法中移动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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM