2017-02-08 29 views
3

У меня есть следующий код:Доступ Kivy размер макета в kvlang

from kivy.app import App 
from kivy.uix.boxlayout import BoxLayout 


class TestGUI(BoxLayout): 
    pass 


class TestApp(App): 
    def build(self): 
     return TestGUI() 


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

и соответствующий .kv файл:

#:kivy 1.9.1 

<TestGUI>: 
    temp_size: (0.5 * x for x in self.size) 
    canvas.before: 
     Color: 
      rgba: (1, 0, 0, 1) 
     Rectangle: 
      size: self.temp_size 

код не запускается, метание:

TypeError: 'NoneType' object is not iterable 

из-за последней строки кода в файле kv. Похоже, что self.size не инициализируется, когда объявляется temp_size, но это вызывает несколько вопросов.

  • Почему я позволил перебирать self.size при объявлении temp_size если это NoneType объект?

  • Кроме того, почему код работает отлично, когда я заменяю последнюю строку size: (0.5 * x for x in self.size) вместо использования переменной?

  • Также, как я могу обойти эту проблему и назначить переменные на основе значения self.size?

+0

это «корень» вместо «я»? https://kivy.org/docs/api-kivy.lang.html –

+0

В этом случае они взаимозаменяемы, но я спрашиваю об общем случае. Например, если 'TestGUI' был вложен в' BoxLayout', тогда это будет 'self.size'. – Kootling

ответ

1

Что здесь происходит, в основном это:

[x for x in None] 

и почему это такое, как, что вы можете прочитать в этом bug report. Это потому, что canvas пока недоступен, и свойства, кажется, были рассчитаны после, поэтому он - если нет canvas, то значение == мусор.

Чтобы исправить это, вы должны сделать это в холст себя, как это и не вне в собственности, так как холст построен первый:

<TestGUI>: 
    canvas.before: 
     Color: 
      rgba: (1, 0, 0, 1) 
     Rectangle: 
      size: (0.5 * x for x in self.size) 

Я не уверен, что вы имеете в виду на последний вопрос, хотя я думаю, что это может быть либо с использованием свойств послеcanvas уже имеются, или с использованием значений из Config, если вы собираетесь использовать Window и не Widget размера, или установить свойство в __init__ и использовать его в дальнейшем в кв.

Последний один может быть лучше для вас, но не забудьте:

  • инициализации с некоторыми значениями (ListProperty([0, 0])) иначе Rectangle будет просто убить того, приложение
  • использование super(), для причины наследования

Пример:

from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.boxlayout import BoxLayout 
from kivy.properties import ListProperty 
Builder.load_string(''' 
<TestGUI>: 
    canvas.before: 
     Color: 
      rgba: (1, 0, 0, 1) 
     Rectangle: 
      size: self.temp_size 
''') 


class TestGUI(BoxLayout): 
    temp_size = ListProperty([0, 0]) 

    def __init__(self, **kwargs): 
     super(TestGUI, self).__init__(**kwargs) 
     print(self.size) 
     self.temp_size = [0.5 * x for x in self.size] 


class TestApp(App): 
    def build(self): 
     return TestGUI() 


if __name__ == '__main__': 
    TestApp().run() 
+0

Но если холст построен до инициализации свойств, то почему 'self.size' не возвращает' None' при настройке размера прямоугольника? – Kootling

+0

@Kootling Я считаю, что я пропустил шаг или два, которые предшествуют созданию холста. Скорее всего, righr до создания холста, свойства size/pos/... доступны для самого холста, но я считаю, что пользовательские из них создаются через мгновение после этого. Однако при использовании в холсте пользовательское свойство вычисляется за мгновение * до * создания холста, но даже до того, как доступны холст size/pos/... (таким образом, size/pos/... - None). – KeyWeeUsr

+0

Это имеет смысл, но почему я не получаю ошибку при установке 'temp_size' в' [x for x in None] '? Я получаю ошибку при настройке размера прямоугольника на 'temp_size'. – Kootling

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

  • Нет связанных вопросов^_^