[英]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.我在创建的
ScreenA
和ScreenB
类中继承了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.