Я хочу, чтобы все переменные для приложения были определены в модуле .py отдельно от файла main.py.Затем я хочу использовать эти переменные внутри файла kivy.
Я пробовал приведенный ниже код с несколькими вариантами, и всегда есть ошибки.Модуль отлично работает, например, для определения различных шрифтов, но когда дело доходит до свойств (ObjectProperty), он не работает.
Структура проекта:
KivyFolder
модули (папка)
экраны (папка)
main.py
- main.kv
Код:
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from os import listdir
from kivy.lang import Builder
kv_screens = './screens/'
for kv in listdir(kv_screens):
Builder.load_file(kv_screens+kv)
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file('main.kv')
class MainApp(App):
import modules.variables
def build(self):
return presentation
if __name__ == '__main__':
MainApp().run()
main.kv
#:kivy 1.10.1
ScreenManagement:
Screen1:
Screen2:
screen1.kv
#:kivy 1.10.1
<Screen1>:
name: 's1'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen 1'
font_size: app.font_size_one
Button:
text: 'Go To Screen 2'
on_press:
root.manager.current = 's2'
screen2.kv
#:kivy 1.10.1
<Screen2>:
name: 's2'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen 2'
font_size: '20dp'
Button:
text: 'Go To Screen 1'
on_press:
root.manager.current = 's1'
variables.py
from kivy.properties import ObjectProperty
font_size_one = ObjectProperty('40dp')
font_size_two = ObjectProperty('60dp')
Теперь, делая это так, выдается эта ошибка:
AttributeError: у объекта 'NoneType' нет атрибута 'bind'
Я бы ожидал, что смогу вызвать переменную, поскольку она импортируется вMainApp (App), поэтому 'app.variable name должно прочитать его.
Я также пробовал:
font_size: app.variables.font_size_one
и:
font_size: app.modules.variables.font_size_one
Затем я попытался импортировать модуль перед всем остальным с тем же результатом.
Я также попытался поместить его в класс и вызвать этот класс в .kv следующим образом:
variables.py
from kivy.properties import ObjectProperty
class FVArs():
font_size_one = ObjectProperty('40dp')
font_size_two = ObjectProperty('60dp')
screen1.kv
#:kivy 1.10.1
<Screen2>:
name: 's2'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen 2'
font_size: FVars().font_size_two
Button:
text: 'Go To Screen 1'
on_press:
root.manager.current = 's1'
Ошибка:
NameError: имя 'FVars' не определено
Спасибо за ваши ответы.
Пока
РЕДАКТИРОВАТЬ: Поскольку ответ нижеработает над примером кода, но не в моем реальном проекте. Я добавляю соответствующий код проекта:
Структура проекта:
KivyFolder
модули (папка)
экраны (папка)
main.py
- main.kv
main.py
from kivy.app import App
from modules.global_variables import globalVariables
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.label import Label
from kivy.properties import StringProperty, NumericProperty, ObjectProperty, Property
from kivy.core.window import Window
background_color = (0.1, 0.1, 0.1, 1)
Window.clearcolor = background_color
from os import listdir
from kivy.lang import Builder
kv_screens = './screens/'
for kv in listdir(kv_screens):
Builder.load_file(kv_screens+kv)
kv_elements = './elements/'
for kv in listdir(kv_elements):
Builder.load_file(kv_elements+kv)
class IntroScreen(Screen):
user_name = StringProperty("Troll")
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("main.kv")
class MainApp(App):
title_size = globalVariables.title_size
def build(self):
self.title = 'Kivy Omnia!'
return presentation
if __name__ == "__main__":
app = MainApp()
app.run()
global_variables.py
from kivy.properties import ObjectProperty
class globalVariables():
title_size = ObjectProperty('101sp')
main.kv
#:kivy 1.10.1
ScreenManagement:
IntroScreen:
intro.kv
#:kivy 1.10.1
<IntroScreen>:
name: "intro"
BoxLayout:
orientation: 'vertical'
Label:
text: "Hello " + root.user_name + "!"
font_size: app.title_size
Ошибка:
kivy.lang.builder.BuilderException: Parser: файл "C: \ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \ Screen \ Intro.kv", строка 10: ... 8: Метка: 9: text: "Hello" + root.user_name + "!"
10: font_size: app.title_size 11: font_name: "Exo-B" 12: AnchorLayout: ... BuilderException: Parser: файл "C: \ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \screen \ Intro.kv", строка 10: ... 8: Метка: 9: текст: "Hello" + root.user_name + "! "10: font_size: app.title_size 11: font_name:" Exo-B "12: AnchorLayout: ... AttributeError: У объекта 'NoneType' нет атрибута 'bind' File 'C: \ Python37-32 \ lib \ site-packages \ kivy \ lang \ builder.py ", строка 249, в create_handler возвращают eval (значение, idmap), файл bound_list, файл" C: \ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \ Screen \ Intro.kv ", строка 10,в файле font_size: app.title_size "C: \ Python37-32 \ lib \ site-packages \ kivy \ lang \ parser.py ", строка 75, в getattribute объект. getattribute (self, _ensure_app ') () Файл" C: \ Python37-32 \ lib \ site-packages\ kivy \ lang \ parser.py ", строка 70, в _ensure_app app.bind (on_stop = лямбда-экземпляр:
Файл" C: \ Python37-32 \ lib \ site-packages "\ kivy \ lang \ builder.py ", строка 615, в _apply_rulerctx ['ids']) Файл "C: \ Python37-32 \ lib \ site-packages \ kivy \ lang \ builder.py", строка 254, в create_handler reason = tb)
Итакесли просто изменить положение:
title_size = globalVariables.title_size
... внутри IntroScreen (Экран), а затем внутри Intro.kv:
font_size: root.title_size
... это работает.Но дело в том, чтобы все глобальные переменные были доступны на всех экранах.
Другой вопрос:
если app.something получает то, что находится внутри основного класса приложения, а root.something получает то, что находится в корневом классе этого файла, тогда как вы вызываете что-то из другого классаэто не приложение или root.Если это имеет смысл.