繁体   English   中英

Python/Kivy 文本输入到 json 文件中的字典

[英]Python/Kivy text input to dictionary in json file

您好我正在尝试添加到存储在 json 文件中的嵌套字典中。 我正在从用户那里获取输入并尝试将它们添加到嵌套字典中。 这是我的代码的一个工作部分......

主要.py:

from kivy.app import App
from kivy.config import Config
from kivy.clock import *
from functools import *
import json
Config.set('graphics', 'width', '480')
Config.set('graphics', 'height', '800')
#Config.set('kivy', 'keyboard_mode', 'dock')
from kivy.uix.screenmanager import *
from kivy.uix.button import *
from kivy.uix.label import *
from kivy.uix.textinput import *
from kivy.clock import *

class SettingsScreen(Screen):

    @mainthread
    def on_enter(self):
        # Drink Manager Tab
        with open("drink_list.json") as f:
            drink_list = json.load(f)
            for drink in drink_list:
                drink_buttons = Button(text=str(drink), size_hint=(None, None))
                self.ids.grid.add_widget(drink_buttons)
        f.close()

        # Add 'Add New Drink' button
        add_new_drink_button = Button(text='Add New Drink', pos=(20, 110), size_hint=(.9, .1))
        add_new_drink_button.bind(on_press=self.add)
        self.ids.done_button_layout.add_widget(add_new_drink_button)

        # Add 'Done!' button
        done_button = Button(text='Done!', pos=(20, 20), size_hint=(.9, .1))
        done_button.bind(on_press=self.done)
        self.ids.done_button_layout.add_widget(done_button)

        # Pump Assignment Tab
        with open("pumps.json") as f:
            test_list = json.load(f)
            for pump in test_list:
                pump_buttons = Button(text=pump + '\n' + test_list[pump]['Ingredient'] + '\n Enabled - ' + str(test_list[pump]['Enabled']), halign='center', size_hint=(None, None))
                self.ids.pump_grid.add_widget(pump_buttons)
                pump_buttons.bind(on_press = partial(self.edit_pump ,pump))
        f.close()

    def add(self, *args):
        self.manager.transition.direction = 'left'
        self.manager.current = 'add_new_drink_screen'

    def done(self, *args):
        self.manager.transition.direction = 'right'
        self.manager.current = 'home_screen'


    def edit_pump(self, pump, *args):
        Test.editing_pump = pump
        self.manager.transition.direction = 'left'
        self.manager.current = 'edit_pump_screen'


    def on_leave(self, *args):
        self.ids.grid.clear_widgets()
        self.ids.pump_grid.clear_widgets()

class AddNewDrinkScreen(Screen):

    @mainthread
    def on_enter(self):
        with open("pumps.json") as f:
            test_list = json.load(f)
            new_drink_name_label = Label(text='Drink Name:\n(Will be displayed on menu)', halign='center', size_hint=(.5, .05))
            self.new_drink_name_input = TextInput(multiline=False, size_hint=(.5, .05))
            new_drink_ingredients_label = Label(text='Ingredients & amount in ML:\nE.g... Rum: 50, Pepsi: 100\nSee ingredients available below (Case sensitive)', halign='center', size_hint=(1, .09))
            self.new_drink_ingredients_input = TextInput(multiline=False, size_hint=(1, .09))
            new_drink_enabled_label = Label(text='Enabled:\n(True or False)', halign='center', size_hint=(.5, .05))
            self.new_drink_enabled_input = TextInput(text='True', multiline=False, size_hint=(.5, .05))
            save_button = Button(text='Save', halign='center', size_hint=(1, .1))
            cancel_button = Button(text='Cancel', halign='center', size_hint=(1, .1))
            self.ids.add_new_drink_grid.add_widget(new_drink_name_label)
            self.ids.add_new_drink_grid.add_widget(self.new_drink_name_input)
            self.ids.add_new_drink_grid.add_widget(new_drink_ingredients_label)
            self.ids.add_new_drink_grid.add_widget(self.new_drink_ingredients_input)
            self.ids.add_new_drink_grid.add_widget(new_drink_enabled_label)
            self.ids.add_new_drink_grid.add_widget(self.new_drink_enabled_input)
            for pump in test_list:
                ingredients_hint = Label(text=test_list[pump]['Ingredient'], halign='center', size_hint=(.2, .05))
                self.ids.add_new_drink_grid.add_widget(ingredients_hint)
            self.ids.add_new_drink_grid.add_widget(save_button)
            self.ids.add_new_drink_grid.add_widget(cancel_button)
            save_button.bind(on_press=self.save_new_drink)
            cancel_button.bind(on_press=self.cancel)
        f.close()

    def save_new_drink(self, instance):
        new_name = self.new_drink_name_input.text
        new_ingredients = self.new_drink_ingredients_input.text
        new_enabled = bool(self.new_drink_enabled_input.text)
        print(new_name)
        print(type(new_name))
        print(new_ingredients)
        print(type(new_ingredients))
        print(new_enabled)
        print(type(new_enabled))

        with open('drink_list.json') as drink_list_file:
            new_drink = json.load(drink_list_file)

            new_drink[new_name] = {'ingredients': {new_ingredients}, 'Enabled': new_enabled}

        with open('drink_list.json', 'w') as drink_list_file:
            json.dump(new_drink, drink_list_file, indent=4)

    def cancel(self, *args):
        self.manager.transition.direction = 'right'
        self.manager.current = 'settings_screen'

    def on_leave(self, *args):
        self.ids.grid3.clear_widgets()

class Test(App):
    editing_pump = ''
    new_drink_name = ''

    pass


Test().run()

测试.kv:

#:kivy 1.9.0
ScreenManager:
    SettingsScreen:
    AddNewDrinkScreen:

<SettingsScreen>:
    name: 'settings_screen'

    TabbedPanel:
        do_default_tab: False
        tab_pos: 'top_mid'
        tab_height: 70
        tab_width: self.width/3
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: self.pos
                size: self.size

        TabbedPanelItem:
            text: 'Drink Manager'

            StackLayout:
                id: grid
                orientation: 'lr-tb'
                padding: 10
                spacing: 10

        TabbedPanelItem:
            text: 'Pump Assignment'

            StackLayout:
                id: pump_grid
                orientation: 'lr-tb'
                padding: 15
                spacing: 15

    FloatLayout:
        id: done_button_layout

<AddNewDrinkScreen>:
    name: 'add_new_drink_screen'

    StackLayout:
        id: add_new_drink_grid
        orientation: 'lr-tb'
        padding: 15
        spacing: 15

json:

{
    "Pump 1": {"Pin": 11, "Ingredient": "Pepsi", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 2": {"Pin": 13, "Ingredient": "Rum", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 3": {"Pin": 15, "Ingredient": "Cherry syrup", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 4": {"Pin": 19, "Ingredient": "Lemon syrup", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 5": {"Pin": 21, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 6": {"Pin": 23, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 7": {"Pin": 29, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 8": {"Pin": 31, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 9": {"Pin": 33, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 10": {"Pin": 35, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 11": {"Pin": 37, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 12": {"Pin": 38, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 13": {"Pin": 36, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 14": {"Pin": 32, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 15": {"Pin": 26, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"},
    "Pump 16": {"Pin": 24, "Ingredient": "Unused", "Pumptime": 0.15, "Enabled": "True"}
}

饮料清单.json:

{
    "Example": {
        "ingredients": {
            "Rum": 50,
            "Pepsi": 100
        },
        "Enabled": false
    }
}

AddNewDrinkScreen 中的输入应填写 save_new_drink 中的变量,然后 save_new_drink 应将这些变量添加到 json 文件中的字典中。 在 new_ingredients 部分之前,这可以正常工作。 我收到 TypeError: Object of type 'set' is not JSON serializable 但无论我尝试什么,我都会得到相同的错误,或者它会将新的饮料和成分添加到字典中,但在成分的两端加上额外的双引号无用。 例如:“'朗姆酒:20,'百事可乐':100”。 有什么想法可以使这项工作或更简单的方法吗?

代码行:

new_drink[new_name] = {'ingredients': {new_ingredients}, 'Enabled': new_enabled}

尝试在new_drink字典中创建一个新条目,但ingredients字典的构建不正确。 new_ingredients变量只是一个字符串,并不构成字典。 为了制作一个实际的字典,您必须解析该字符串。 这是您的save_new_drink()方法的修改版本,它可以做到这一点:

def save_new_drink(self, instance):
    new_name = self.new_drink_name_input.text

    # make dictionary to hold new ingredients
    new_ingredients = {}

    # parse input into the new_ingredients dict
    tokens = self.new_drink_ingredients_input.text.split(',')
    for tok in tokens:
        ingredient, amount = tok.split(':')
        new_ingredients[ingredient.strip()] = int(amount.strip())

    new_enabled = bool(self.new_drink_enabled_input.text)
    print(new_name)
    print(type(new_name))
    print(new_ingredients)
    print(type(new_ingredients))
    print(new_enabled)
    print(type(new_enabled))

    with open('drink_list.json') as drink_list_file:
        new_drink = json.load(drink_list_file)

        # use the constructed dictionary of ingredients
        new_drink[new_name] = {'ingredients': new_ingredients, 'Enabled': new_enabled}

    with open('drink_list.json', 'w') as drink_list_file:
        json.dump(new_drink, drink_list_file, indent=4)

我不认为上面的代码在生产代码中是可用的,但它展示了这个想法。 解析用户输入很困难。 您可能需要考虑一种不同的方法。 也许对配方使用readonlyTextInput ,通过单击Buttons来填充成分,并使用带有input_filter: 'int'TextInput来填充数量。 然后,您可以使用ast.literal_eval()TextInput构建字典。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM