访问 kivy 文件中的 python 列表

Access python list in kivy file

我是一名物理学家,众所周知,我们喜欢我们的鸡尾酒。因此,我正在尝试构建一个自动调酒师。不幸的是,我在 python 编程的唯一经验是进行物理模拟,而且我对编码并不那么精通。

我的问题现在是这样的:class BartenderApp 中有一个 python 列表,我想在 kivy 文件中使用它,特别是在kivy 文件中的 LoadNewIngredients,供微调器从中选择。我已经寻找了很长一段时间的解决方案,none 到目前为止已经奏效了。我知道我应该能够使用 for 循环将微调器和标签放入 python 文件中,但我更希望它更干净一些并将它们保存在 kivy 文件中。

因此,如果有人可以帮助我如何将列表传递给 kivy 文件,将不胜感激!

这里是 .py 文件:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.clock import mainthread
from functools import partial
#Import drink list
from drinks import drink_list, drink_options

class drink:
    def __init__(self,name,ingredients,amount):
        self.name = name
        self.ingredients = ingredients
        self.amount = amount

#Define the different screens
class MainMenu(Screen):
    pass

class UseLastIngredients(Screen):
    pass

class DrinkMenu(Screen):

    #Mainthread will pause shortly to give script time, the rest adds the buttons
    @mainthread
    def on_enter(self):
        self.buttons = []
        self.ids.drinks.clear_widgets()
        for btn in range(len(drink_list)):
            self.buttons.append(Button(text=str(drink_list[btn]['name'])))
            self.buttons[btn].bind(on_press = self.pour_drink)
            self.ids.drinks.add_widget(self.buttons[btn])


    def pour_drink(self, button):
        print(button.text)


class LoadNewIngredients(Screen):
    def spinner_clicked(self, ident, value):
        if ident == 1:
            pass
        if ident == 2:
            pass
        if ident == 3:
            pass
        if ident == 4:
            pass
        if ident == 5:
            pass
        if ident == 6:
            pass
        if ident == 7:
            pass
        if ident == 8:
            pass


#Define the ScreenManager
class MenuManager(ScreenManager):
    pass

#Designate the .kv design file
kv = Builder.load_file('bartenderkv.kv')

class BartenderApp(App):

    #I want to use the ingredients list in the kivy file
    global ingredients
    ingredients = []
    for drink in range(len(drink_list)):
        ings = list(drink_list[drink]['ingredients'].keys())
        for ing in range(len(ings)):
            elem = ings[ing]
            if elem not in ingredients:
                ingredients.append(elem)

    def build(self):
        return kv

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

这里是 .kv 文件:

#:import Factory kivy.factory.Factory
#:import ScrollView kivy.uix.scrollview

MenuManager:
    MainMenu:
    LoadNewIngredients:
    DrinkMenu:

<MainMenu>:
    name: "MainMenu"
    GridLayout:
        rows: 3
        size: root.width, root.height
        padding: 10
        spacing: 10

        Label:
            text: "Main Menu"
            font_size: 32

        GridLayout:
            cols: 2
            size: root.width, root.height
            spacing: 10
            Button:
                text: "Use Last Ingredients"
                font_size: 32
                on_release: app.root.current = "DrinkMenu"
            Button:
                text: "Load New Ingredients"
                font_size: 32
                on_release: app.root.current = "LoadNewIngredients"
        Button:
            text: "See Permissable Ingredients"
            font_size: 32
            #on_press: print("It Works")
            on_release: Factory.PermissablePopup().open()

<LoadNewIngredients>:
    name: "LoadNewIngredients"
    GridLayout:
        cols: 2
        size: root.width, root.height
        padding: 10
        spacing: 10

        GridLayout:
            size: root.width, root.height
            size_hint_x: 0.4
            rows: 2
            Button:
                text: "Continue"
                font_size: 24
                on_release: app.root.current = "DrinkMenu"
            Button:
                text: "Main Menu"
                font_size: 24
                on_release: app.root.current = "MainMenu"
        GridLayout:
            
            #This is where I want the spinners to take in the ingredients list as options.

            id: choices
            rows: 4
            orientation: 'tb-lr'
            Label:
                id: pump_1
                text: "Pump 1"
                font_size: 24
            Label:
                id: pump_2
                text: "Pump 2"
                font_size: 24
            Label:
                id: pump_3
                text: "Pump 3"
                font_size: 24
            Label:
                id: pump_4
                text: "Pump 4"
                font_size: 24
            #Spinner is the easy drop down version in kivy, lets see how it looks.
            Spinner:
                id: spinner_id_1
                text: "Pump_1"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(1,spinner_id_1.text)

            Spinner:
                id: spinner_id_2
                text: "Pump_2"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(2,spinner_id_2.text)

            Spinner:
                id: spinner_id_3
                text: "Pump_3"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(3,spinner_id_3.text)

            Spinner:
                id: spinner_id_4
                text: "Pump_4"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(4,spinner_id_4.text)

            Label:
                id: pump_5
                text: "Pump 5"
                font_size: 24
            Label:
                id: pump_6
                text: "Pump 6"
                font_size: 24
            Label:
                id: pump_7
                text: "Pump 7"
                font_size: 24
            Label:
                id: pump_8
                text: "Pump 8"
                font_size: 24
            #Spinner is the drop down version, lets see how it looks.
            Spinner:
                id: spinner_id_5
                text: "Pump_5"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(5,spinner_id_5.text)

            Spinner:
                id: spinner_id_6
                text: "Pump_6"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(6,spinner_id_6.text)

            Spinner:
                id: spinner_id_7
                text: "Pump_7"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(7,spinner_id_7.text)

            Spinner:
                id: spinner_id_8
                text: "Pump_8"
                values: ["1", "2", "3"]
                on_text: root.spinner_clicked(8,spinner_id_8.text)

<DrinkMenu>:
    name: "DrinkMenu"
    GridLayout:
        cols: 2
        width: root.width
        height: self.minimum_height
        padding: 10
        spacing: 10
        GridLayout:
            height: root.height
            size_hint_x: 0.4
            rows: 2
            Button:
                text: "Top Up"
                font_size: 24
                on_release:
            Button:
                text: "Main Menu"
                font_size: 24
                on_release: app.root.current = "MainMenu"
        ScrollView:
            size_hint_y: 0.73
            pos_hint: {'x':0, 'y': 0.11}
            do_scroll_x: False
            do_scroll_y: True

            GridLayout:
                id: drinks
                orientation: 'lr-tb'
                size_hint_y: None
                size_hint_x: 1.0
                cols: 3
                height: self.minimum_height
                row_default_height: 180
                row_force_default: True

#Create a rounded button, the @Button is what it inherits
<RoundedButton@Button>
    background_color: (0,0,0,0)
    background_normal: ''
    canvas.before:
        Color:
            rgba:
                (48/255,84/255,150/255,1)\
                if self.state == 'normal' else (0.6,0.6,1,1) # Color is red if button is not pressed, otherwise color is green
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [58]

<PermissablePopup@Popup>
    auto_dismiss: False
    #size_hint: 0.6,0.2
    #pos_hint: {"x":0.2, "top":0.9}
    title: "Permissable Ingredients"
    GridLayout:
        rows: 2
        size: root.width, root.height
        spacing: 10
        GridLayout:
            cols: 2
            Label:
                text: "Sodas"
                font_size: 32
                #Add list of sodas
            Label:
                text: "Alcohol"
                font_size: 32
                #Add list of alcohols

        Button:
            text: "Done"
            font_size: 24
            on_release: root.dismiss()

尝试向您的应用添加一个 ListProperty (https://kivy.org/doc/stable/api-kivy.properties.html) class。像这样:

class BartenderApp(App):

    ingredients = ListProperty() 
    
    for drink in range(len(drink_list)):
        ings = list(drink_list[drink]['ingredients'].keys())
        for ing in range(len(ings)):
            elem = ings[ing]
            if elem not in self.ingredients:
                self.ingredients.append(elem)

列表 属性 可在 Python 和 KV 文件中访问。更重要的是,它们可以绑定到回调,以便您可以创建自己的事件!

您现在可以在 KV 文件中引用 app.ingredients 并且当 app.ingredients 更改时,列表定义的任何对象都会自动更新。例如,如果您的 KV 文件中有以下标签:

Label:
    text: app.ingredients[0]

当您更改列表时,文本会自动更新。不过要小心,如果您引用的索引中没有对象,您可能会遇到索引错误。

请告诉我您的进展情况以及它是否解决了您的问题。

我终于设法解决了它,也许不是最好的解决方案,但它有效。

在 class LoadNewIngredients 中,我编写了一个函数来检查可用的成分和 returns 包含成分的列表。然后使用 root.function_name().

在 kivy 应用程序中引用此函数

.py 文件:

#Everything needed for kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.clock import mainthread
from functools import partial
#Import drink list
from drinks import drink_list, drink_options

class drink:
    def __init__(self,name,ingredients,amount):
        self.name = name
        self.ingredients = ingredients
        self.amount = amount

#Define the different screens
class MainMenu(Screen):
    pass

class UseLastIngredients(Screen):
    pass

class DrinkMenu(Screen):

    #Mainthread will pause shortly to give script time, the rest adds the buttons
    @mainthread
    def on_enter(self):
        self.buttons = []
        self.ids.drinks.clear_widgets()
        for btn in range(len(drink_list)):
            self.buttons.append(Button(text=str(drink_list[btn]['name'])))
            self.buttons[btn].bind(on_press = self.pour_drink)
            self.ids.drinks.add_widget(self.buttons[btn])

    def pour_drink(self, button):
        print(button.text)

class LoadNewIngredients(Screen):
    def spinner_clicked(self, ident, value):
        if ident == 1:
            pass
        if ident == 2:
            pass
        if ident == 3:
            pass
        if ident == 4:
            pass
        if ident == 5:
            pass
        if ident == 6:
            pass
        if ident == 7:
            pass
        if ident == 8:
            pass
    #I want to use the ingredients list in the kivy file
    def get_ingredients(self,*args,**kwargs):
        global ingredients
        ingredients = []
        for drink in range(len(drink_list)):
            ings = list(drink_list[drink]['ingredients'].keys())
            for ing in range(len(ings)):
                elem = ings[ing]
                if elem not in ingredients:
                    ingredients.append(elem)
        return ingredients


#Define the ScreenManager
class MenuManager(ScreenManager):
    pass

#Designate the .kv design file
kv = Builder.load_file('bartenderkv.kv')

class BartenderApp(App):

    def build(self):
        return kv

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

这里是 .kv 文件:

#Need to define everything, the ScreenManager is the entity that keeps tabs
#on all the different menu windows

#This is for the popup, lets you instansiate a class from anywhere
#:import Factory kivy.factory.Factory
#:import ScrollView kivy.uix.scrollview

MenuManager:
    MainMenu:
    LoadNewIngredients:
    DrinkMenu:

<MainMenu>:
    name: "MainMenu"
    GridLayout:
        rows: 3
        size: root.width, root.height
        padding: 10
        spacing: 10

        Label:
            text: "Main Menu"
            font_size: 32

        GridLayout:
            cols: 2
            size: root.width, root.height
            spacing: 10
            Button:
                text: "Use Last Ingredients"
                font_size: 32
                on_release: app.root.current = "DrinkMenu"
            Button:
                text: "Load New Ingredients"
                font_size: 32
                on_release: app.root.current = "LoadNewIngredients"
        Button:
            text: "See Permissable Ingredients"
            font_size: 32
            on_release: Factory.PermissablePopup().open()

<LoadNewIngredients>:
    name: "LoadNewIngredients"
    GridLayout:
        cols: 2
        size: root.width, root.height
        padding: 10
        spacing: 10
        #size hint sets relative sized, x-dir, y-dir
        GridLayout:
            size: root.width, root.height
            size_hint_x: 0.4
            rows: 2
            Button:
                text: "Continue"
                font_size: 24
                on_release: app.root.current = "DrinkMenu"
            Button:
                text: "Main Menu"
                font_size: 24
                on_release: app.root.current = "MainMenu"
        GridLayout:
            id: choices
            rows: 4
            orientation: 'tb-lr'
            Label:
                id: pump_1
                text: "Pump 1"
                font_size: 24
            Label:
                id: pump_2
                text: "Pump 2"
                font_size: 24
            Label:
                id: pump_3
                text: "Pump 3"
                font_size: 24
            Label:
                id: pump_4
                text: "Pump 4"
                font_size: 24
            Spinner:
                id: spinner_id_1
                text: "Pump_1"
                #This references the get_ingredients function in the main py file
                values: root.get_ingredients()
                on_text: root.spinner_clicked(1,spinner_id_1.text)

            Spinner:
                id: spinner_id_2
                text: "Pump_2"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(2,spinner_id_2.text)

            Spinner:
                id: spinner_id_3
                text: "Pump_3"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(3,spinner_id_3.text)

            Spinner:
                id: spinner_id_4
                text: "Pump_4"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(4,spinner_id_4.text)

            Label:
                id: pump_5
                text: "Pump 5"
                font_size: 24
            Label:
                id: pump_6
                text: "Pump 6"
                font_size: 24
            Label:
                id: pump_7
                text: "Pump 7"
                font_size: 24
            Label:
                id: pump_8
                text: "Pump 8"
                font_size: 24
            Spinner:
                id: spinner_id_5
                text: "Pump_5"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(5,spinner_id_5.text)

            Spinner:
                id: spinner_id_6
                text: "Pump_6"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(6,spinner_id_6.text)

            Spinner:
                id: spinner_id_7
                text: "Pump_7"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(7,spinner_id_7.text)

            Spinner:
                id: spinner_id_8
                text: "Pump_8"
                values: root.get_ingredients()
                on_text: root.spinner_clicked(8,spinner_id_8.text)

<DrinkMenu>:
    name: "DrinkMenu"
    GridLayout:
        cols: 2
        width: root.width
        height: self.minimum_height
        padding: 10
        spacing: 10
        GridLayout:
            height: root.height
            size_hint_x: 0.4
            rows: 2
            Button:
                text: "Top Up"
                font_size: 24
                on_release:
            Button:
                text: "Main Menu"
                font_size: 24
                on_release: app.root.current = "MainMenu"
        ScrollView:
            size_hint_y: 0.1
            pos_hint: {'x':0, 'y': 0.11}
            do_scroll_x: False
            do_scroll_y: True

            GridLayout:
                id: drinks
                orientation: 'lr-tb'
                size_hint_y: None
                size_hint_x: 1.0
                cols: 3
                height: self.minimum_height
                row_default_height: 100
                row_force_default: True

<RoundedButton@Button>
    background_color: (0,0,0,0)
    background_normal: ''
    canvas.before:
        Color:
            rgba:
                (48/255,84/255,150/255,1)\
                if self.state == 'normal' else (0.6,0.6,1,1)
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [58]

<PermissablePopup@Popup>
    auto_dismiss: False
    #size_hint: 0.6,0.2
    #pos_hint: {"x":0.2, "top":0.9}
    title: "Permissable Ingredients"
    GridLayout:
        rows: 2
        size: root.width, root.height
        spacing: 10
        GridLayout:
            cols: 2
            Label:
                text: "Sodas"
                font_size: 32
                #Add list of sodas
            Label:
                text: "Alcohol"
                font_size: 32
                #Add list of alcohols

        Button:
            text: "Done"
            font_size: 24
            on_release: root.dismiss()

如果其他人遇到同样的问题,希望这对您有所帮助。 但是,如果有人有任何其他解决方案(或对一般代码的建议),请告诉我!