【问题标题】:Python/Kivy: Manual settings page - actualize text size in .kv-filePython/Kivy:手动设置页面 - 在 .kv 文件中实现文本大小
【发布时间】:2017-10-29 21:02:10
【问题描述】:

我正在尝试在我的 Kivy 应用中实现手动创建的设置页面。在这种情况下,我在使用应用程序内部的实际设置时遇到了问题。为了演示这个问题,请使用这个最小的例子:

Python 文件“main.py”,我在其中尝试在两个全局变量 first_size 和 second_size 中写入当前字体大小,然后我想在 Kivy 文件中访问它们:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from settingsjson import settings_json
from kivy.properties import NumericProperty

import settings

class MainMenu(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("style.kv")

class MyApp(App):
    def build(self):
        global first_size, second_size
        first_size = NumericProperty(settings.sizes[settings.options[0]]["first_label"])
        second_size = NumericProperty(settings.sizes[settings.options[0]]["second_label"])
        return presentation

    def build_config(self, config):
        config.setdefaults('settings', {
            'test_size': settings.options[0]
            })

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

    def reset_labels(self, first_labelsize, second_labelsize):
        global first_size, second_size
        first_size = NumericProperty(first_labelsize)
        second_size = NumericProperty(second_labelsize)

    def on_config_change(self, config, section, key, value):
        first_labelsize = settings.sizes[value]['first_label']
        second_labelsize = settings.sizes[value]['second_label']
        self.reset_labels(first_labelsize, second_labelsize)

myApp = MyApp()
myApp.run()

Python 文件“settingsjson.py”,包含新的设置页面:

import json
import settings

settings_json = json.dumps([
    {'type': 'title',
     'title': 'Settings'},
    {'type': 'options',
     'title': 'Size',
     'desc': 'Test size',
     'options': settings.options,
     'section': 'settings',
     'key': 'test_size'}])

将设置菜单中的两个选项与字体大小相关联的字典的 Python 文件“settings.py”:

options = ['small', 'large']

small = {'first_label': 20, 'second_label': 15}
large = {'first_label': 30, 'second_label': 25}

sizes = {options[0]: small, options[1]: large}

最后是 Kivy 文件“style.kv”:

ScreenManagement:
    MainMenu:

## accessing first global variable (not working)
<Button>:
    font_size: root.first_size

## accessing second global variable (not working either)
<TwoLineButton@Button>:
    font_size: root.second_size


<MainMenu>:
    name: "main"
    FloatLayout:
        Button:
            size_hint: 0.5, 0.2
            pos_hint: {"top": 0.5, "right": 1}
            text: "One-line dummy"
        TwoLineButton:
            size_hint: 0.5, 0.2
            pos_hint: {"top": 0.5, "left": 1}
            text: "This is a two-line\n dummy"
            halign: "center"

        Button:
            on_release:
                app.open_settings()
            text: "Settings"
            font_size: self.height/4
            pos_hint: {"top": 0.1, "right": 0.5}
            size_hint: 0.2, 0.1

如您所见,当前形式的代码不起作用,因为我无法访问 Kivy 文件中的两个字体大小变量。如果我将 Kivy 文件中的 font_size 属性设置为常量值,应用程序运行没有问题,但当然不允许设置菜单中的更改生效。

有没有办法在Kivy文件中访问main.py-file中的全局变量来重置两种按钮的字体大小?

由于我必须在不止一个屏幕中更改设置,因此我需要一个全局独立于类的解决方案。

我很感激每一种提示......

【问题讨论】:

    标签: python-3.x global-variables kivy kivy-language


    【解决方案1】:

    这里有一个稍微不同的方法,使用 on_ 回调在数值属性改变时自动改变字体大小。注意first_size和second_size必须在加载style.kv之前定义

    Main.py:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from settingsjson import settings_json
    from kivy.properties import NumericProperty
    
    import settings
    
    class MainMenu(Screen):
        pass
    
    class ScreenManagement(ScreenManager):
        pass
    
    
    class MyApp(App):
        first_size = NumericProperty(settings.sizes[settings.options[0]]["first_label"])
        second_size = NumericProperty(settings.sizes[settings.options[0]]["second_label"])
    
        def on_first_size(self, instance, value):
            self.main_menu.ids['button1'].font_size = value
    
        def on_second_size(self, instance, value):
            self.main_menu.ids['button2'].font_size = value
    
        def build(self):
            presentation = Builder.load_file("style.kv")
            self.main_menu = presentation.current_screen
            return presentation
    
        def build_config(self, config):
            config.setdefaults('settings', {
            'test_size': settings.options[0]
            })
    
        def build_settings(self, settings):
            settings.add_json_panel('Own Settings',
                                self.config,
                                data=settings_json)
    
        def on_config_change(self, config, section, key, value):
            self.first_size = settings.sizes[value]['first_label']
            self.second_size = settings.sizes[value]['second_label']
    
    myApp = MyApp()
    myApp.run()
    

    和style.kv:

    ScreenManagement:
    MainMenu:
    
    <MainMenu>:
        name: "main"
        FloatLayout:
            Button:
                id: button1
                font_size: app.first_size
                size_hint: 0.5, 0.2
                pos_hint: {"top": 0.5, "right": 1}
                text: "One-line dummy"
            Button:
                id: button2
                font_size: app.second_size
                size_hint: 0.5, 0.2
                pos_hint: {"top": 0.5, "left": 1}
                text: "This is a two-line\n dummy"
                halign: "center"
    
            Button:
                on_release:
                    app.open_settings()
                text: "Settings"
                font_size: self.height/4
                pos_hint: {"top": 0.1, "right": 0.5}
                size_hint: 0.2, 0.1
    

    【讨论】:

    • 其实,你甚至不需要 on_first_size() 和 on_second_size() 函数。它们可以被删除。
    • 首先感谢您的回复!这有很大帮助!我有三个更具体的后续问题:1)似乎应用程序在关闭时保存了大小设置选择('大','小')以供下次启动。但是,由于 first_size 和 second_size 变量是在启动应用程序时手动默认的,因此选择和实际文本大小有时不匹配。有没有办法在两个变量的“尝试(使用上次的设置)...除了(使用默认设置)”中直接访问上次应用程序启动时保存的信息?
    • 2) 有没有办法重置设置菜单中“取消”和“关闭”按钮的标题,例如将它们翻译成不同的语言?
    • 3) 在标准菜单中更改设置(例如,全屏模式或旋转)时,更改仅在手动重新启动应用程序时应用。如何在更改时自动启动重新启动或直接应用更改的设置而不重新启动?
    • 对于问题1,在您的 build() 方法中,添加:` text_size = self.config['settings']['test_size'] self.first_size = settings.sizes[text_size]["first_label" ] self.second_size = settings.sizes[text_size]["second_label"]` 在调用 Builder.load() 之前。这也意味着您创建的 NumericProperties 可以只是“NumericProperty(0)”。
    【解决方案2】:

    不确定这是否适合您,但在 .kv 文件中删除您的 Button 和 TwoLineButton 定义,并从布局中的实际 Button 定义中访问 root.first_size 和 root.second_size:

    FloatLayout:
        Button:
            font_size: root.first_size
            size_hint: 0.5, 0.2
            pos_hint: {"top": 0.5, "right": 1}
            text: "One-line dummy"
        Button:
            font_size: root.second_size
            size_hint: 0.5, 0.2
            pos_hint: {"top": 0.5, "left": 1}
            text: "This is a two-line\n dummy"
            halign: "center"
    

    它引用的“根”是“MainMenu”,因此在您的 MainMenu 类中添加类级别变量“first_size”和“second_size”:

    class MainMenu(Screen):
        first_size = NumericProperty(settings.sizes[settings.options[0]]["first_label"])
        second_size = NumericProperty(settings.sizes[settings.options[0]]["second_label"])
    

    由于这些不是实例变量,您可以在导入 MainMenu 的任何位置将它们作为“MainMenu.first_size”和“MainMenu.second_size”引用。

    【讨论】:

    • 不幸的是,这个解决方案似乎对我不起作用......字体大小保持不变,因为 MyApp 类的“刷新”操作只影响这个类。我不知何故需要能够从 MyApp 类中访问“get_setting”方法来确定哪个设置当前处于活动状态......但是,也许我没有正确理解你......你能详细说明你的解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多