我有一个带有设置的kivy应用,我希望为某些用户禁用某些设置(例如' General')。我试着走路了#39;通过设置的孩子(使用禁用的设置),但我似乎无法这样做。
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.uix.settings import SettingsWithSidebar
import json
settings_general = json.dumps([
{'type': 'title',
'title': 'Set general preferences'},
{'type': 'bool',
'title': 'Use widgets',
'desc': 'Allow the use of widgets in the application',
'section': 'general',
'key': 'use widgets'},
{'type': 'bool',
'title': 'Print log',
'desc': 'Print log on closing application',
'section': 'general',
'key': 'print log'}
])
settings_appearance = json.dumps([
{'type': 'title',
'title': 'Appearance preferences'},
{'type': 'bool',
'title': 'Use colour',
'desc': 'Allow the use of colour in the application',
'section': 'appearance',
'key': 'use colour'}
])
class MainFrame(Screen):
def __init__(self, **kwargs):
super(MainFrame, self).__init__(**kwargs)
pass
def on_settings_button_click(self):
settings = self.app.settings_cls
print('type settings', type(settings))
print('is SettingsWithSidebar', isinstance(settings,
SettingsWithSidebar))
self.app.open_settings()
def on_quit_button_click(self):
quit()
class Settings(object):
def build_config(self, config):
config.setdefaults('general',
{
'use widgets': 0,
'print log': 0
})
config.setdefaults('appearance',
{
'use colour': 0
})
def build_settings(self, parent, settings):
settings.add_json_panel('General',
parent.config,
data=settings_general)
settings.add_json_panel('Appearance',
parent.config,
data=settings_appearance)
class BasicApp(App):
def build(self):
main_frame = MainFrame()
main_frame.app = self
self.settings_cls = SettingsWithSidebar
self.use_kivy_settings = False
return main_frame
def build_config(self, config):
self.settings = Settings()
self.settings.build_config(config)
def build_settings(self, settings):
self.settings.build_settings(self, settings)
if __name__ == '__main__':
BasicApp().run()
我的kv文件是:
<MainFrame>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Settings'
on_press: root.on_settings_button_click()
Button:
text: 'Click to close'
on_press: root.on_quit_button_click()
有人可以建议我可以使用的方法吗?
[本节不需要阅读] 在我被允许发布之前我必须输入更多文本(我认为代码与文本的比例)。这似乎很遗憾,因为这个问题很简单,我想提供一个应用程序的基本工作示例,这个示例必然非常冗长。 [额外文字的结尾]
答案 0 :(得分:1)
您可以使用disabled
属性禁用面板中的项目。
settings_general = json.dumps([
{'type': 'title',
'title': 'Set general preferences'},
{'type': 'bool',
'disabled': True,
'title': 'Use widgets',
'desc': 'Allow the use of widgets in the application',
'section': 'general',
'key': 'use widgets'}])
此示例中禁用了第二项。
但是,我没有找到一种直观的方法来禁用整个Appearance
部分。例如
所以我选择了一种hackery方法
首先是走settings
小部件树,找到那个标签。
tab = list(self.app.settings.walk(loopback=True))[5]
在这种情况下,我发现标签是第6个元素
但仅将disable
属性设置为True
是不够的。它会标记掉标签,但它仍然可以点击它,因为它们使用了on_touch_down
方法
所以我们可以覆盖on_touch_down
方法
我在应用程序类中添加了一个切换到大型机和切换方法,以测试它。
<MainFrame>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Settings'
on_press: root.on_settings_button_click()
Switch:
on_active: app.toggle_setting(self.active)
Button:
text: 'Click to close'
on_press: root.on_quit_button_click()
I found the original on_touch_down method here
def on_touch_down(touch, self):
# we need to write this method to override back to the original method
# the original method was found in kivy/uix/settings.py.
# look at the link above
if not self.collide_point(*touch.pos):
return
self.selected = True
self.menu.selected_uid = self.uid
class MainFrame(Screen):
def on_settings_button_click(self):
self.app.open_settings()
tab = list(self.app.settings.walk(loopback=True))[5]
if not self.app.toggle: # if switch is inactive
tab.disabled = True
tab.on_touch_down = lambda x: False
else:
tab.disabled = False
# we need partial from functools, so we can pass the tab as self
tab.on_touch_down = partial(on_touch_down,self=tab)
def on_quit_button_click(self):
quit()
完整的代码:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.uix.settings import SettingsWithSidebar
from kivy.lang import Builder
import json
from functools import partial
settings_general = json.dumps([
{'type': 'title',
'title': 'Set general preferences'},
{'type': 'bool',
'disabled': True,
'title': 'Use widgets',
'section': 'general',
'key': 'use widgets'}
])
settings_appearance = json.dumps([
{'type': 'title',
'title': 'Appearance preferences'},
{'type': 'bool',
'title': 'Use colour',
'section': 'appearance',
'key': 'use colour'}
])
def on_touch_down(touch, self):
if not self.collide_point(*touch.pos):
return
self.selected = True
self.menu.selected_uid = self.uid
class MainFrame(Screen):
def on_settings_button_click(self):
self.app.open_settings()
tab = list(self.app.settings.walk(loopback=True))[5]
if not self.app.toggle:
tab.disabled = True
tab.on_touch_down = lambda x: False
else:
tab.disabled = False
tab.on_touch_down = partial(on_touch_down,self=tab)
def on_quit_button_click(self):
quit()
Builder.load_string("""
<MainFrame>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Settings'
on_press: root.on_settings_button_click()
Switch:
on_active: app.toggle_setting(self.active)
Button:
text: 'Click to close'
on_press: root.on_quit_button_click()
""")
class BasicApp(App):
toggle = False
def build(self):
self.main = MainFrame()
self.main.app = self
self.settings_cls = SettingsWithSidebar
self.use_kivy_settings = False
return self.main
def build_config(self, config):
self.config = config
self.config.setdefaults('general',{'use widgets': 0,'print log': 0})
self.config.setdefaults('appearance',{'use colour': 0})
def build_settings(self, settings):
self.settings = settings
self.settings.add_json_panel('General', self.config, data=settings_general)
self.settings.add_json_panel('Appearance', self.config, data = settings_appearance)
def toggle_setting(self, active):
self.toggle = active
BasicApp().run()