I am building an App and using the kivy settingspanel to change settings. Some of the settings are stored in ConfigParserProperties and can also be changed outside of the settings panel. When I reopen the settings panel the values in the settings panel are still the old ones.
How can I update the settings panel with the most recent values (in the ConfigParserProperties)?
I found this Dynamically updated Kivy settings entry But here only 1 widget is created which updates (a list popup). I am looking for a way to update multiple settings items of different types.
The only way I got the settings panel to update is by destroying it and recreating it every time it is opened (for code see below). This is a (noticeably) slow process if the panel contains multiple pages (which is not the case in this example to keep things simple).
This example generates a random value for variable test, which is the only item in the settings panel (open it by clicking the button or pressing f1). As you can see the value will not change from the start value.
from kivy.app import App
from kivy.properties import ConfigParserProperty
from random import randint
from kivy.clock import Clock
from kivy.uix.button import Button
import json
class MyApp(App):
test = ConfigParserProperty(0, 'testing', 'test_par', 'app_config', val_type=int)
use_kivy_settings = False # disable kivy settings in options
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_interval(self.new_number, 1)
def build(self):
self.config.read("test.ini")
self.config.name = "app_config"
_app = super().build()
_app.add_widget(Button(text='open settings',
size=_app.size,
pos=_app.pos,
on_release=self.open_settings))
return _app
def build_settings(self, settings):
_setts = json.dumps([
{
"type": "title",
"title": "Test Settings"
},
{
"type": "numeric",
"title": "Test Var",
"desc": "Randomly changing test var, wish it would change here too",
"section": "testing",
"key": "test_par"
}])
settings.add_json_panel('Test Panel', self.config, data=_setts)
self.settings = settings
def new_number(self, *args, **kwargs):
# generate random new values for test
self.test = randint(0, 0xff)
print(self.test)
if __name__ == "__main__":
app = MyApp()
app.run()
What I tried:
Adding this code will change the value every time the panel is opened. But also destroys and recreates the panel everytime you open it. Which is slow with multiple panel items.
def open_settings(self, *args):
self.destroy_settings() # clear settings
return super().open_settings(*args)
If anyone knows a way to change/update specific panel items with changes in the ConfigParserProperties, much appreciated.
Had the same problem. My solution was to manually update the value of each SettingItem after changing the ConfigParser object. For this you can simply iterate over the panels of your settings widget:
from kivy.uix.settings import SettingItem
# ...
settings = <my setting widget instance>
panels = settings.interface.content.panels
for panel in panels.values():
children = panel.children
for child in children:
if isinstance(child, SettingItem):
child.value = panel.get_value(child.section, child.key)
# ...
Maybe you have to adjust the path to the panels (.interface.content.panels), depending of the type of settings widget you use (I used default SettingsWithSidebar). The panel.get_value method gets the actual value directly out of the initially assigned ConfigParser instance.