【问题标题】:Kivy settings do not update the .ini in androidKivy 设置不会更新 android 中的 .ini
【发布时间】:2021-04-15 05:31:19
【问题描述】:

简而言之: 我的设置文件 (vocab.ini) 刚刚在我的笔记本电脑上更新,不知何故在 Android 上没有更新(可能是权限?)。

你好!

我正在努力实现以下目标:

我有一个应用程序,它的设置保存在一个外部 .ini 文件 (vocab.ini) 中。每当设置中的某些内容发生更改时,实现的on_config_change() 方法将使用更改后的 .ini 文件重新初始化所有屏幕,以便相应地更新我的所有屏幕并使更改持久化(例如在应用程序关闭后)。 这样做的逻辑已经存在,但不知何故,它只能在我的笔记本电脑上运行,而不是在我的智能手机上。

这就引出了我的第一个问题:

我真的不明白为什么在我更改应用程序中的某些内容后更新 vocab.ini 文件(在我的笔记本电脑上 - 它不会在 android 上更新),因为我没有实现类似 config.set() 和/或config.write() 在我的代码中。不知何故,on_config_change() 必须暗示,因为我可以在笔记本电脑上实时看到当我点击六个可用选项中的任何一个时内容如何变化。

我的第二个问题一般来说是如何实现这样的逻辑,这也适用于 Android/任何智能手机,因为我必须错过某事。或者对 kivy 中的设置面板的工作方式有误解。

这是一个简短的代码 sn-p 应该可以帮助您重现问题。

main.py:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.actionbar import ActionBar
from kivy.properties import ObjectProperty
from settingsjson import settings_json
from kivy.config import ConfigParser

config = ConfigParser()

def get_config():
    config.read('vocab.ini')

class MainWindow(Screen):
    label = ObjectProperty(None)
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        print("Initialized Main!")
        get_config()
        self.label = "Current config: {}".format(config.get('example','optionsexample'))

class Manager(ScreenManager):
    pass

KV = Builder.load_file("vocabApp.kv")

class vocabApp(App):    
    def build_config(self, config):
        config.setdefaults('example', {
            'optionsexample': 'HSK1'})
        config.read('vocab.ini')

    def build_settings(self, settings):
        settings.add_json_panel('Vocab Settings',
                                self.config,
                                data=settings_json)

    def on_config_change(self, config, section,
                         key, value):
        print("Re-initialize all screens")

        ### For android debugging ###
        f = open("vocab.ini", "r")
        print(f.read())
        ###                       ###
        for sc in self.root.ids.sm.screen_names:
            self.root.ids.sm.get_screen(sc).__init__()

    def build(self):
        return KV

if __name__ == "__main__":
    vocabApp().run()

vocabApp.kv:

BoxLayout:
    id: sm
    orientation: 'vertical'

    ActionBar:
        background_image: ''
        background_color: (0.53, 0.808, 0.98, 1)
        ActionView:
            ActionPrevious:
            ActionButton:
                text: 'Settings'
                on_release: app.open_settings()
        
    ScreenManager:
        id: sm
        MainWindow:

<MainWindow>:
    name: 'main'
    Label:
        id: label
        text: root.label

settingsjson.py

import json

settings_json = json.dumps([
    {'type': 'title',
     'title': 'example title'},
    {'type': 'options',
     'title': 'HSK Level',
     'desc': 'Choose the difficulty (HSK1 to HSK6)',
     'section': 'example',
     'key': 'optionsexample',
     'options': ['HSK1', 'HSK2', 'HSK3', 'HSK4', 'HSK5', 'HSK6']}
])

vocab.ini:

[example]
optionsexample = HSK1

【问题讨论】:

    标签: python android kivy settings configparser


    【解决方案1】:

    不确定这是否会解决它,但这是我的处理方式:

    from kivy.utils import platform
    import os.path
    
    
    def get_config_file_name():
        if platform == 'android':
            from android.storage import app_storage_path
            return os.path.join(app_storage_path(), 'vocab.ini')
        else:
            return os.path.join(os.path.expanduser('~'), 'vocab.ini')
    
    
    from kivy.config import Config
    
    
    def permissions_callback_storage(requests, grants):
        if grants[0]:
            Config.read(get_config_file_name())
    
    
    if platform == 'android':
        perms = ['android.permission.WRITE_EXTERNAL_STORAGE']
        from android.permissions import request_permissions
        request_permissions(perms, callback=permissions_callback_storage)
    else:
        Config.read(get_config_file_name())
    

    【讨论】:

    • 你好约翰!感谢您的回答,但不幸的是,这并不能解决我的问题。可能我实现错了,但如果我理解正确的话,我也有点困惑,因为你使用的是默认的 kivy 配置。尤其是在我的 vocabApp 类中,事情变得一团糟,因为没有 ConfigParser。但是我通过正则表达式手动读取和编辑文件来解决它,尽管这可能不是最优雅的方法:)
    【解决方案2】:

    通过在vocabApp()类的on_config_change()方法中添加手动读写代码解决:

    def on_config_change(self, config, section,
                         key, value):
        print("Re-initialize all screens")
    
        with open("vocab.ini", "r") as f:
            subbed = re.sub("{}(.*)".format(key), "{} = {}".format(key, value), f.read())
    
        with open("vocab.ini", "w") as f:
            f.write(subbed)
    
        for sc in self.root.ids.sm.screen_names:
            self.root.ids.sm.get_screen(sc).__init__()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      相关资源
      最近更新 更多