简体   繁体   English

使用 Kivy 切换屏幕:AttributeError: 'NoneType' object has no attribute 'transition'

[英]Switching screens using Kivy: AttributeError: 'NoneType' object has no attribute 'transition'

I've run into an AttributionError when trying to call a "screen switch" function defined in one class from another using kivy library in python.当我尝试使用 python 中的 kivy 库调用另一个 class 中定义的“屏幕切换”function 时,我遇到了AttributionError

The structure of my code is as follows:我的代码结构如下:

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App

def init_grid(width, height, mines):
    global grid_field
    global flagged
    # Initiate the gird field with empty grids
    grid_field = [[ClassA() for i in range(width)] for j in range(height)]
    flagged = 0
    ...


class Main(App):
   def build(self):
      sm = ScreenManager()

      current = Current(name="current")
      screenA = ScreenA(name="screenA")
      screenB = ScreenB(name="screenB")
      ...
      ...

      sm.add_widget(current)
      sm.add_widget(screenA)
      sm.add_widget(screenB)
      ...
      ...

      sm.current = "current"
      return sm

...

class ClassA():
    # a class my code is at when the error arises, 
    # which is not the starting "current" screen class 
    # but a different class that serves a certain purpose to my program
    def __init__(self, **kwargs):
        ...
        ...
        self.button = Button()
        self.button.bind(on_touch_down=self.method)


    def method(self, instance, touch):
        if (a condition):
            ScreenA().change_to_B()

    ...




...


class ScreenA(Screen):
    def __init__(self, **kwargs):
        Screen.__init__(self, **kwargs)
        ...
        ...
        init_grid(10, 10, 10)

    def change_to_B(self):
        self.manager.transition.direction = "left"
        self.manager.current = "screenB"


...


class ScreenB(Screen):
    def __init__(self, **kwargs):
        Screen.__init__(self, **kwargs)
        ...
        ...


if __name__ == '__main__':
    Main().run()

The error message is:错误信息是:

in change_to_B
     self.manager.transition.direction = "left"
 AttributeError: 'NoneType' object has no attribute 'transition'

From my code above, I defined the screen-switch function change_to_B in class ScreenA , and I called this function in class ClassA .从我上面的代码中,我在 class ScreenA中定义了屏幕开关 function change_to_B ,我在 class ClassA中调用了这个 function 。 I have inherited the Screen parent class in the both classes ScreenA and ScreenB I have created.我在创建的ScreenAScreenB类中继承了Screen父级 class。 But strangely enough, the error message seems to suggest that the object screenA is a NoneType object, which shouldn't be the case as I have declared that to be screen object when creating the class by inheriting the Screen parent class.但奇怪的是,错误消息似乎表明 object screenA是一个NoneType object,这不应该是这种情况,因为我在通过继承Screen父 class 创建 class 时声明它是屏幕 object。

Can anyone point out what is the mistake I am missing out?谁能指出我遗漏的错误是什么? Thank you in advance!!!先感谢您!!!

EDIT:编辑:

I think I need to make clear of my code.我想我需要弄清楚我的代码。 So I'm basically trying to write the minesweeper game and the ClassA is the grid that the gameboard of minesweeper consists of, and it has a Button attribute to implement the clicking function method (shown in the code above).所以我基本上是在尝试编写扫雷游戏, ClassA是扫雷游戏板组成的网格,它有一个Button属性来实现点击 function method (如上面的代码所示)。 In the clicking function method , I was trying to call the screen-switch function change_to_B() defined in class ScreenA , which is a screen object declared in the build method of the ScreenManager (I think).在点击 function method时,我试图调用 class ScreenA中定义的屏幕开关 function change_to_B() ,这是在 ScreenManager 的构建方法中声明的屏幕 object(我认为)。

The flow of the code is: Current(name="current") (which is irrelavent to this question) --> ScreenA(name="screenA"), where ClassA() is created in the global list variable from function init_grid() --> ClassA(), where clicking on the UI calls the function binded to the Button attributes of the ClassA() objects.代码的流程是:Current(name="current")(与本题无关)--> ScreenA(name="screenA"),其中ClassA()是在function init_grid() --> ClassA(),点击 UI 调用绑定到ClassA()对象的Button属性的 function。

The ClassA object is created in a function init_grid , where a global variable grid_field is created to store the ClassA objects in a 2D list.在 function init_grid 中创建了ClassA init_grid ,其中创建了全局变量grid_field以将ClassA对象存储在二维列表中。

Common mistake - you use more than one object of each screens, so you add one object to ScreenManager and that object has property manager .常见错误 - 每个屏幕使用了多个 object,因此您将一个 object 添加到ScreenManager并且该 object 具有 property manager But then you create another object of ScreenA class here:但是然后你在这里创建另一个 object 的ScreenA class:

def __init__(self, **kwargs):
        ...
        ...
        ScreenA().change_to_B()

Screen Manager knows nothing about that object. So the thing you should keep in mind is that you add objects to screen manager, not classes .屏幕管理器对 object 一无所知。所以你应该记住的是你向屏幕管理器添加objects ,而不是classes You didn't provide the whole code so I don't know where you define the object of ClassA class, but you should pass object from build method there to make it work.您没有提供完整的代码,所以我不知道您在哪里定义了ClassA class 的 object,但是您应该从那里的build方法中传递 object 以使其工作。 Something like this:是这样的:

class ScreenA(Screen):
    def __init__(self, **kwargs):
        Screen.__init__(self, **kwargs)
        ...
        ...
        # here we pass the object of the ScreenA class (which is self) to init grid to be able to pass it to ClassA
        init_grid(10, 10, 10, self)

# add object to arguments
def init_grid(width, height, mines, screenA):
    global grid_field
    global flagged
    # pass the object to ClassA
    grid_field = [[ClassA(screenA) for i in range(width)] for j in range(height)]

class classA():
    # don't forget to add object to arguments
    def __init__(self, screenA, **kwargs):
        ...
        ...
        self.screenA = screenA

    def method(self, instance, touch):
        if (a condition):
            self.screenA.change_to_B()

Or with global variables:或者使用全局变量:

current = Current(name="current")
screenA = ScreenA(name="screenA")
screenB = ScreenB(name="screenB")

class Main(App):
   def build(self):
      sm = ScreenManager()

      global current
      global screenA
      global screenB
      ...
      ...

      sm.add_widget(current)
      sm.add_widget(screenA)
      sm.add_widget(screenB)
      ...
      ...

      sm.current = "current"
      return sm

class ClassA():
    def method(self, instance, touch):
        global screenA
        if (a condition):
            screenA.change_to_B()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AttributeError:'NoneType'对象没有属性'text'kivy - AttributeError: 'NoneType' object has no attribute 'text' kivy Kivy AttributeError: 'NoneType' object 没有属性 'current' - Kivy AttributeError: 'NoneType' object has no attribute 'current' Kivy AttributeError: 'NoneType' object 没有属性 'ids' - Kivy AttributeError: 'NoneType' object has no attribute 'ids' Python Kivy AttributeError: 'NoneType' 对象没有属性 'bind' - Python Kivy AttributeError: 'NoneType' object has no attribute 'bind' Kivy AttributeError: 'NoneType' 对象没有属性 'get_screen' - Kivy AttributeError: 'NoneType' object has no attribute 'get_screen' Kivy Scrollview: AttributeError: 'NoneType' 对象没有属性 'bind' - Kivy Scrollview: AttributeError: 'NoneType' object has no attribute 'bind' Kivy:AttributeError:'NoneType' 对象没有属性 'add_widget' - Kivy: AttributeError: 'NoneType' object has no attribute 'add_widget' Python-Kivy AttributeError: 'NoneType' object 没有属性 'text' - Python-Kivy AttributeError: 'NoneType' object has no attribute 'text' Kivy Builder: AttributeError: 'NoneType' 对象没有属性 'text' - Kivy Buildozer: AttributeError: 'NoneType' object has no attribute 'text' AttributeError: 'NoneType' 对象没有属性 - AttributeError: 'NoneType' object has no attribute
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM