2014-11-13 2 views
6

UPDATE: ответПочему я не могу получить доступ к Screen.ids?

Ryan P, при условии решения. Однако я принял это решение и немного изменил его, выбросив все данные, которые не были , правильно инициализированы в методе on_enter на RootWidget Экран. Это сработало хорошо.

Класс My RootWidget был подклассифицирован Виджет до сегодняшнего дня, и у меня не было проблем с доступом к его идентификаторам, чтобы получить значение «сетки». Тем не менее, я просто изменил его на подкласс Screen, и теперь он говорит, что по какой-то причине идентификаторы пустые ... Экран имеет идентификаторы и все такое, но по какой-то причине он не регистрирует это Я назначил GridLayout к id '' grid '' в файле kv. Может ли кто-нибудь сказать мне, почему?

отслеживающий:

[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' 

киловольт файл:

#: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' 

main.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() 
+0

из журнала он выглядит, как вы используете v1.9.0_dev. Нет проблем с добавлением идентификатора на экран в v1.8.0. Вы пробовали тот же код с этой версией? – tiktok

+0

У меня нет. Я не уверен, как можно понизить рейтинг – Totem

+0

Можете ли вы разместить больше кода, чтобы он был выполнен, и я попробую его на своей машине? – tiktok

ответ

7

правила ТРАНСФОРМАЦИЯ не применяются до го e original Widget закончил создание экземпляра. В этом случае ваш виджет 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 
+1

Это сработало! И я чувствую, что должен был видеть это, порядок, в котором все происходило. Благодаря! Я должен сказать, однако, этот вопрос раздражает меня, мне не нравится, что это должно быть сделано в том, что похоже на исправленный вид. – Totem

+2

Это похоже на улучшение, которое мы могли бы сделать. Не стесняйтесь отправлять запрос функции на https://github.com/kivy/kivy/issues или найти решение и сделать запрос на перенос :) –

Смежные вопросы