Как отключить раздел в настройках Kivy? - PullRequest
0 голосов
/ 31 мая 2018

У меня есть приложение kivy с настройками, и я хочу отключить некоторые настройки (например, «Общие») для определенных пользователей.Я пытался пройтись по дочерним элементам настроек (чтобы использовать отключенные настройки), но я не могу этого сделать.

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()

Может кто-нибудь предложить какой-нибудь подход, который я могу использовать?

[Этот раздел читать не нужно] Мне нужно ввести больше текста, прежде чем мне разрешат это опубликовать (соотношение кода и текста, я думаю).Это кажется позором, потому что вопрос очень прост, и я хотел привести базовый рабочий пример приложения, которое, по необходимости, довольно многословно.[конец дополнительного текста]

1 Ответ

0 голосов
/ 31 мая 2018

Вы можете отключить элементы на панели с атрибутом 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.
Итак, я выбрал хакерский метод.
Сначала нужно было пройтись по виджету 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()

Я нашел оригинальный метод on_touch_down здесь

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...