如何在kivy中使用在另一个.py模块(不是main.py)中定义的变量?

时间:2019-02-05 14:00:14

标签: python kivy kivy-language

我希望将.py模块中定义的应用程序的所有变量与main.py文件分开。然后我想在kivy文件中使用这些变量。

我尝试了以下代码,并进行了多种更改,并且始终会出现错误。该模块可以很好地用于定义例如不同的Fonts,但是当涉及properties(ObjectProperty)时,它将无法正常工作。

项目结构:

  • KivyFolder

    • 模块(文件夹)

      • variables.py
    • 屏幕(文件夹)

      • screen1.kv

      • screen2.kv

    • 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

    • 模块(文件夹)

      • global_variables.py
    • 屏幕(文件夹)

      • Intro.kv

      • (以及其他屏幕作为单独的.kv文件

    • 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:解析器:文件   “ C:\ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \ screens \ Intro.kv”,行   10:...          8:标签:          9:文本:“ Hello” + root.user_name +“!”

     
    
      

10:font_size:app.title_size             11:font_name:“ Exo-B”             12:AnchorLayout:... BuilderException:解析器:文件“ C:\ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \ screens \ 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”文件       “ C:\ Python37-32 \ lib \ site-packages \ kivy \ lang \ builder.py”,第249行,在       create_handler            返回eval(值,idmap),绑定列表文件“ C:\ Users \ Ghost \ CodeProjects \ phyton \ kivyomnia \ screens \ Intro.kv”,行       10,在            font_size:app.title_size文件“ C:\ Python37-32 \ lib \ site-packages \ kivy \ lang \ parser.py”,第75行,在       获取属性            对象。 getattribute ((自身,'_ ensure_app')()文件“ C:\ Python37-32 \ lib \ site-packages \ kivy \ lang \ parser.py”,第70行,在       _ensure_app            app.bind(on_stop = lambda实例:

    
  
     

文件“ C:\ Python37-32 \ lib \ site-packages \ kivy \ lang \ builder.py”,行   615,在_apply_rule中        rctx ['ids'])文件“ C:\ Python37-32 \ lib \ site-packages \ kivy \ lang \ builder.py”,第254行,在   create_handler        cause = tb)

因此,只要重新定位:

title_size = globalVariables.title_size

...在IntroScreen(屏幕)内,然后在Intro.kv内:

font_size: root.title_size

...有效。但是关键是要在所有屏幕上都提供所有全局变量。

另一个问题:

如果app.something得到主应用程序类内部的内容 然后root.something获取该文件的根类中的内容,然后如何从另一个非app或root的类中调用某些内容。如果这样的话。

1 个答案:

答案 0 :(得分:0)

您可以使用此行导入FVars类:

from modules.variables import FVars

然后在MainApp类中,可以使用FVars的类变量的数据创建一个类变量。

class MainApp(App):
    f1 = FVars.font_size_one

然后您可以在您的kv文件中访问它:

font_size: app.f1

这是一些基本示例:

main.py

from kivy.app import App
from kivy.lang import Builder

from modules.variables import FVars

class Test(App):
    f1 = FVars.font_size_one

    def build(self):
        return Builder.load_file("test.kv")

Test().run()

test.kv

BoxLayout:
    Label:
        text: "Hello"
        font_size: app.f1

modules / variables.py

from kivy.properties import ObjectProperty

class FVars():
    font_size_one = ObjectProperty('40dp')
    font_size_two = ObjectProperty('60dp')

更新

为防止错误,您可以在build方法内加载kv文件。

def build(self):                         
    self.title = 'Kivy Omnia!'           

    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)  

    presentation = Builder.load_file("main.kv") 

    return presentation

关于如何访问既不是app也不是root的类中的变量,有很多方法,您只需设置该小部件的id属性即可。

这是一个基本示例:

main.py

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

class SecondClass(BoxLayout):
    someNumber = 123 # Let's say we wanted to print the value of this variable when we press the button.

class FirstClass(BoxLayout):
    pass

class TestApp(App):

    def build(self):
        return FirstClass()


TestApp().run()

test.kv

<SecondClass>:

<FirstClass>:

    Button: 
        text: "Print the Numbah"
        on_press: print(app.root.ids.secondclass.someNumber) # We can do something like this
    SecondClass:
        id: secondclass

我们还可以执行以下操作:

<SecondClass>:

<FirstClass>:

    Button: 
        text: "Print the Numbah"
        on_press: print(root.ids.secondclass.someNumber) 
    SecondClass:
        id: secondclass

或者这个:

<SecondClass>:

<FirstClass>:

    Button: 
        text: "Print the Numbah"
        on_press: print(secondclass.someNumber)
    SecondClass:
        id: secondclass

甚至是这样:

<SecondClass>:

<FirstClass>:
    second: secondclass
    Button:
        text: "Print the Numbah"
        on_press: print(app.root.second.someNumber)

    SecondClass:
        id: secondclass

这:

<SecondClass>:

<FirstClass>:
    second: secondclass
    Button:
        text: "Print the Numbah"
        on_press: print(root.second.someNumber)
    SecondClass:
        id: secondclass