gpt4 book ai didi

python - 为什么我不能访问 Screen.ids?

转载 作者:太空狗 更新时间:2023-10-29 21:39:47 25 4
gpt4 key购买 nike

更新:

Ryan P's answer provided the solution. However, I took that solution and changed it up a bit, throwing all of the data that wasn't being properly initialised into the on_enter method of the RootWidget Screen. This has worked nicely.

直到今天,我的 RootWidget 类都是 Widget 的子类,访问它的 ID 以获取“grid”的值时我没有遇到任何问题。然而,我只是改变了它是 Screen 的子类,现在它说由于某种原因 ids 是空的......Screen 确实有一个 ids 等等,但由于某种原因,它没有注册我将 GridLayout 分配给 kv 文件中的 id ''grid''。谁能告诉我为什么?

回溯:

[INFO   ] [Logger      ] Record log in /home/yerman/.kivy/logs/kivy_14-11-13_201.txt
[INFO ] Kivy v1.9.0-dev
[INFO ] [Python ] v2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2]
[INFO ] [Factory ] 172 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_pygame, img_pil, img_gif (img_sdl2, img_ffpyplayer ignored)
[INFO ] [Window ] Provider: pygame(['window_egl_rpi'] ignored)
[WARNING] [WinPygame ] Video: failed (multisamples=2)
[WARNING] [WinPygame ] trying without antialiasing
[INFO ] [GL ] OpenGL version <2.1 Mesa 10.1.3>
[INFO ] [GL ] OpenGL vendor <Intel Open Source Technology Center>
[INFO ] [GL ] OpenGL renderer <Mesa DRI Intel(R) Ironlake Mobile >
[INFO ] [GL ] OpenGL parsed version: 2, 1
[INFO ] [GL ] Shading version <1.20>
[INFO ] [GL ] Texture max size <8192>
[INFO ] [GL ] Texture max units <16>
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[INFO ] [Text ] Provider: pygame(['text_sdl2'] ignored)
{} #<<< note the emtpy ids I printed out
Traceback (most recent call last):
File "main.py", line 169, in <module>
MineSweeperApp().run()
File "/usr/lib/python2.7/dist-packages/kivy/app.py", line 799, in run
root = self.build()
File "main.py", line 163, in build
return Manager()
File "/usr/lib/python2.7/dist-packages/kivy/uix/screenmanager.py", line 844, in __init__
super(ScreenManager, self).__init__(**kwargs)
File "/usr/lib/python2.7/dist-packages/kivy/uix/floatlayout.py", line 66, in __init__
super(FloatLayout, self).__init__(**kwargs)
File "/usr/lib/python2.7/dist-packages/kivy/uix/layout.py", line 66, in __init__
super(Layout, self).__init__(**kwargs)
File "/usr/lib/python2.7/dist-packages/kivy/uix/widget.py", line 269, in __init__
Builder.apply(self)
File "/usr/lib/python2.7/dist-packages/kivy/lang.py", line 1837, in apply
self._apply_rule(widget, rule, rule)
File "/usr/lib/python2.7/dist-packages/kivy/lang.py", line 1942, in _apply_rule
child = cls(__no_builder=True)
File "main.py", line 43, in __init__
self.grid = self.ids["grid"]
KeyError: 'grid'

kv文件:

#:kivy 1.8.0

<RootWidget>:
GridLayout:
id: grid
size: root.size
cols: root.sides

<Blank>:
background_color: 1, 1, 1, 1
background_disabled_down: "kivy_white_bg.png"
on_press: self.parent.parent.sweep(self)

<Mine>:
background_color: 1, 1, 1, 1
background_disabled_down: "kivy_white_bg.png"
on_press: self.parent.parent.sweep(self)

<TryAgain>:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
size: root.size
orientation: 'vertical'
padding_bottom: '20dp'

Label:
font_size: '20dp'
text: root.text

BoxLayout:
size_hint: 1, .3
spacing: 10
padding: 10
Button:
size_hint: .4, 1
font_size: '20dp'
text: "yes"
on_press: app.stop(); app.run()
Button:
size_hint: .4, 1
font_size: '20dp'
text: "no"
on_press: root.quit()

<Menu>:
GridLayout:
rows: 2
Button:
text: "8x8"
on_press: root.manager.current = 'game_screen'
Button:
text: "16x16"
on_press: root.manager.current = 'game_screen'
Button:
text: "30x16"
on_press: root.manager.current = 'game_screen'
Button:
text: "custom"
on_press: root.manager.current = 'game_screen'

<Manager>:
id: _manager
menu: menu
game: game
current: menu_screen

Menu:
id: menu
manager: _manager
name: 'menu_screen'

RootWidget:
id: game
manager: _manager
name: 'game_screen'

ma​​in.py:

#!/usr/bin/env python

from random import sample
import sys
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.properties import NumericProperty, ListProperty, StringProperty, ObjectProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.modalview import ModalView
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock

class Blank(Button):

index = ListProperty([0, 0])
count = NumericProperty(0)

def __init__(self, **kwargs):
super(Blank, self).__init__(**kwargs)


class Mine(Button):

index = ListProperty([0, 0])
count = NumericProperty(0) # not really necessary

def __init__(self, **kwargs):
super(Mine, self).__init__(**kwargs)


class RootWidget(Screen):

sides = NumericProperty(10)
mine_count = NumericProperty(20)

def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.grid = self.ids["grid"]

# generate random mine indices
mines = sample(xrange(self.sides**2), self.mine_count)

x, y = -1, 0
for i in xrange(self.sides**2):
if x == self.sides - 1:
x = 0
y += 1
else:
x += 1

if i not in mines:
b = Blank(index=[x, y])

else:
b = Mine(index=[x, y])
self.grid.add_widget(b)

# record mine, blank and safe blank indices
self.all_btns = [c.index for c in self.grid.children]
self.mines = [c.index for c in self.grid.children if isinstance(c, Mine)]
self.blanks = [c.index for c in self.grid.children if isinstance(c, Blank)]
# a safe blank has no adjacent mines
self.safe_blanks = [c.index for c in self.grid.children if self.is_safe(c)]

# give each btn an 'adjacent mines count'
for x, y in self.all_btns:
btn = self.get_child_by_index([x, y])
for index in self.field(x, y):
if index in self.mines:
btn.count += 1

def field(self, x, y):
""" the minefield surrounding a btn """
field = [[x-1, y], [x+1, y], [x, y+1], [x, y-1],
[x+1, y+1], [x-1, y-1], [x+1, y-1], [x-1, y+1]]

get = self.get_child_by_index
return [i for i in field if i in self.all_btns and get(i).disabled == False]

def sweep(self, instance):
instance.disabled = True

if instance.index in self.mines:
print "Boom!" # It's a mine! You lose
instance.text = "Boom!"
self.game_over()

pressed = sum(1 for c in self.grid.children if c.disabled == True)
print pressed
if self.sides**2 - pressed == self.mine_count:
self.game_over(win=True)

if instance.count > 0:
instance.text = str(instance.count)
instance.disabled = True
return
else:
x, y = instance.index

for index in self.field(x, y):
if index not in self.mines:
blank = self.get_child_by_index(index)
blank.disable = True
if blank.count > 0:
blank.text = str(blank.count)
self.sweep(blank)

def is_safe(self, btn):
x, y = btn.index
for index in self.field(x, y):
if index in self.mines:
return False
return True

def get_child_by_index(self, index):
for child in self.grid.children:
if child.index == index:
return child

def game_over(self, q=False, win=False):
if q == True:
sys.exit()

if win == True:
result = "Win"
elif win == False:
result = "lost"

view = TryAgain(
size_hint = (None, None),
width = self.width/2,
height = self.height/2,
center = self.center,
text = "You {}! Try Again?".format(result))
view.open()

class TryAgain(ModalView):

text = StringProperty('')

def quit(self):
sys.exit()

class Menu(Screen):
pass


class Manager(ScreenManager):

menu = ObjectProperty(None)
game = ObjectProperty(None)


class MineSweeperApp(App):

def build(self):
return Manager()



if __name__ == "__main__":

MineSweeperApp().run()

最佳答案

在原始 Widget 完成实例化之前,不会应用 kv 规则。在这种情况下,您的 Manager 小部件是初始小部件 - 它依次创建其他小部件,包括 RootWidget。这意味着在您的 RootWidget.__init__ 中,ids 尚未填充!它们将在 Manager 完成实例化后立即出现 - 因此最好的方法是延迟其余的初始化,如下所示:

class RootWidget(Screen):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
Clock.schedule_once(self._finish_init)

def _finish_init(self, dt):
self.grid = self.ids.grid
# etc

关于python - 为什么我不能访问 Screen.ids?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26916262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com