Kivy 与异步。在 .kv 文件中更改屏幕时出错

Kivy with asyncio. Error when changing screen in .kv file

我减少了我的代码,只关注我遇到的问题。 我的代码的 asyncio 部分正在运行 - 我为这些过程留下了存根。 当我合并我的用户界面 kivy 代码和我的 asyncio kivy 代码时,我在屏幕更改时收到上述错误。 我 认为 我需要在其中安装一个带有 Builder.load_file() 的“应用程序”??,但我的尝试失败了。 希望有人能帮忙? 单击“Post 一张照片!”按钮我收到这个错误...

   File "C:\TEMP\kivy1\kivy_venv\src\screens.kv", line 31, in <module>
     on_press: app.switch_screen='TakePhotoScreen'
   File "C:\TEMP\kivy1\kivy_venv\lib\site-packages\kivy\lang\parser.py", line 83, in __setattr__
     object.__getattribute__(self, '_ensure_app')()
   File "C:\TEMP\kivy1\kivy_venv\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'

代码:screen.kv

Manager:
    TestMyFeedScreen3:
    TakePhotoScreen:

#:import ScrollEffect kivy.effects.scroll.ScrollEffect
#:import Window kivy.core.window.Window

<TestMyFeedScreen3>:
    name:'TestMyFeedScreen3'
    id:TestMyFeedScreen3
    orientation: 'vertical'

    GridLayout:
        cols:1
        rows:2
        height: 50
        Label:
            text: 'My Story'
            size_hint_y: None
            height: 50
        GridLayout:
            cols:2
            rows:1
            height: 50
            Button:
                text: 'Post a Photo!'
                size_hint_y: None
                height: '48dp'
                # ERROR HERE >>>>>>>>>>>>>>>>>>>>>>>>>>>>
                #on_press: app.root.current='TakePhotoScreen'
                on_press: app.switch_screen='TakePhotoScreen'  
            Button:
                text: 'Back'
                size_hint_y: None
                height: '48dp'
                on_release:
                    app.root.current='TestMyFeedScreen3'
                    root.manager.transition.direction = "left"

    ScrollView:
        effect_cls: ScrollEffect
        size_hint: 1, None
        size: Window.width, (Window.height -100)
        bar_width: 5
        bar_color: 1, 0, 0, 1   # red
        bar_inactive_color: 0, 0, 1, 1   # blue
        scroll_type: ['bars','content']     # move scrool by bar or photos

        GridLayout:
            id:picsx
            do_scroll_x: False
            height: self.minimum_height
            size_hint_y: None
            spacing: 3, 3
            cols: 3
            Button:
                #text:'Pic'
                background_normal: "Image1.PNG"
                background_down: 'Click.PNG'
                size_hint_y:None
                height:100


<TakePhotoScreen>:
    name:'TakePhotoScreen'
    orientation: 'vertical'
    GridLayout:
        cols:1
        rows:3
        Button:
            text: 'Take Photo and Post It !'
            size_hint_y: None
            height: '48dp'

        Button:
            text: 'Back'
            size_hint_y: None
            height: '48dp'

        Image:
            id: imageView
            source: 'mob_photo.jpg'
            allow_stretch: True

代码:mainx.py

# This code has been cut down to focus on the error
from __future__ import print_function

import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.lang import Builder
from kivy.config import Config
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout


import asyncio
from kivy.app import async_runTouchApp
from kivy.cache import Cache
import aioconsole

from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty


images = 1
#client_number = sys.argv[1]
client_number = "0"
print("This is client " + client_number)

Config.set('graphics', 'width', '380')
Config.set('graphics', 'height', '700')

async def send_messages(writer, stdin):
    print("In send_messages stub")

async def receive_messages(reader, stdout):
    print("In receive_messages stub")


async def run_client():
    print("In run_client")

代码

# This code has been cut down to focus on the error
from __future__ import print_function

import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.lang import Builder
from kivy.config import Config
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout


import asyncio
from kivy.app import async_runTouchApp
from kivy.cache import Cache
import aioconsole

from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty


images = 1
#client_number = sys.argv[1]
client_number = "0"
print("This is client " + client_number)

Config.set('graphics', 'width', '380')
Config.set('graphics', 'height', '700')

async def send_messages(writer, stdin):
    print("In send_messages stub")

async def receive_messages(reader, stdout):
    print("In receive_messages stub")


async def run_client():
    print("In run_client")


# Screen code

class TestMyFeedScreen3(Screen):
    pass

class TakePhotoScreen(Screen):
    pass

class Manager(ScreenManager):
    pass

kv=Builder.load_file('screens.kv')
root = kv

async def run_app_happily(root, other_task):
    # This method, which runs Kivy, is run by the asyncio loop as one of the coroutines.

    # we don't actually need to set asyncio as the lib because it is the
    # default, but it doesn't hurt to be explicit
    await async_runTouchApp(root, async_lib='asyncio')  # run Kivy
    print('App done')
    # now cancel all the other tasks that may be running
    other_task.cancel()


if __name__ == '__main__':
    def root_func():

        while True:
            print("In __main__")
            other_task = asyncio.ensure_future(run_client())
            return asyncio.gather(run_app_happily(kv, other_task), other_task)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(root_func())
    loop.close()

由于您的代码中没有实际的 App,因此您不能在行中引用它:

on_press: app.switch_screen='TakePhotoScreen'

但您可以参考 ScreenManager 并像这样更改 current Screen

        Button:
            text: 'Post a Photo!'
            size_hint_y: None
            height: '48dp'
            # ERROR HERE >>>>>>>>>>>>>>>>>>>>>>>>>>>>
            on_press: root.manager.current='TakePhotoScreen'

您的代码中其他地方也有类似情况。