【问题标题】:Issue when using ScreeManager with Kivy- buttons layout no longer works使用带有 Kivy 按钮布局的 ScreeManager 时的问题不再有效
【发布时间】:2017-06-30 02:16:29
【问题描述】:

所以我在尝试使用屏幕管理器时遇到了问题。因为我必须创建我的屏幕类现在是 (Screen) 而不是 (GridLayout) 才能使用 screenmanager,例如,按钮/布局管理不能再在 python 中控制了吗?它曾经在屏幕上布置 5 列和 3 行,总共 15 个按钮。现在它只显示一个大的(屏幕)而不是网格布局。

class LandingScreen(Screen):
def build(self):
    return presentation
def __init__(self, **kwargs):
    super(LandingScreen, self).__init__(**kwargs)
    self.cols = 5
    self.buttons = []  # add references to all buttons here

    # Loop to make 20 different buttons on screen
    for x in range(15):
        self.buttons.append(Button(text='button ' + str(x)))  # make a reference to the button before adding it in
        self.add_widget(self.buttons[x])
        self.buttons[x].background_normal = 'YOUTUBE.png'

此处的按钮和列设置用于使用此循环创建 3 行,每行 5 个按钮,因为我将 (Screen) 添加到类而不是 (GridLayout),所以它没有。我宁愿不在 .kv 文件中创建所有按钮,因为我认为在 .py 中更容易管理并且对我来说更有意义。

这是我的 .kv 文件:

<GridLayout>:
    cols: 5
    height: 480
    width: 800
    spacing: 25, 20
    padding: 25,25

<MyScreenManager>:
    LandingScreen:
    InputScreen:

<InputScreen>:
    AnchorLayout:

<LandingScreen>:
    GridLayout:
        cols: 5
        height: 480
        width: 800
        spacing: 25, 20
        padding: 25,25

这显然是多余的,因为我试图弄清楚如何让所有 15 个按钮再次显示,而不仅仅是一个。

谢谢!

【问题讨论】:

    标签: python python-3.x user-interface kivy kivy-language


    【解决方案1】:

    您希望将按钮添加到 GridLayout 内的 Screen,而不是直接添加到 Screen。为此,请使用id 来引用GridLayout

    但是,您不能在__init__ 方法中使用id,因为在相应的小部件完全初始化之前不会应用kv 文件中定义的规则。 Ryan Pi 在这个问题中正确提供了解决方案:

    Why can't I access the Screen.ids?

    另一方面,稍后要更改屏幕,您必须在屏幕中定义 name 属性。

    你的代码应该是:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.uix.button import Button
    from kivy.clock import Clock
    
    
    kv_text='''\
    
    <MyScreenManager>:
        LandingScreen:
        InputScreen:
    
    <InputScreen@Screen>:
        name: 'input_sc'
        AnchorLayout:
            id: anchor_1
    
    <LandingScreen@Screen>:
        name: 'landing_sc'
        GridLayout:
            id: grid_1
            cols: 5
            height: 480
            width: 800
            spacing: 25, 20
            padding: 25,25
    '''
    
    class MyScreenManager(ScreenManager):
        pass
    
    
    class LandingScreen(Screen):
        def __init__(self, **kwargs):
            super(LandingScreen, self).__init__(**kwargs)
            self.buttons = [] # add references to all buttons here
            Clock.schedule_once(self._finish_init)
    
        def _finish_init(self, dt):
            self.ids.grid_1.cols = 5
    
            # Loop to make 20 different buttons on screen
            for x in range(15):
                self.buttons.append(Button(text='button {}'.format(x)))
                self.ids.grid_1.add_widget(self.buttons[x])
                self.buttons[x].background_normal = 'YOUTUBE.png'
    
    class MyKivyApp(App):
        def build(self):
            return MyScreenManager()
    
    def main():
        Builder.load_string(kv_text)
        app = MyKivyApp()
        app.run()
    
    if __name__ == '__main__':
        main()
    

    如果您想使用Properties 而不是ids 方法(请参阅documentation),您应该执行以下操作:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.uix.button import Button
    from kivy.clock import Clock
    from kivy.properties import ObjectProperty
    
    
    kv_text='''\
    
    <MyScreenManager>:
        LandingScreen:
        InputScreen:
    
    <InputScreen@Screen>:
        name: 'input_sc'
        AnchorLayout:
            id: anchor_1
    
    <LandingScreen@Screen>:
        name: 'landing_sc'
        grid_1: grid_1
        GridLayout:
            id: grid_1
            cols: 5
            height: 480
            width: 800
            spacing: 25, 20
            padding: 25,25
    '''
    
    class MyScreenManager(ScreenManager):
        pass
    
    
    class LandingScreen(Screen):
    
        grid_1 = ObjectProperty(None)    #<<<< Propertie
    
        def __init__(self, **kwargs):
            super(LandingScreen, self).__init__(**kwargs)
            self.buttons = [] # add references to all buttons here
            Clock.schedule_once(self._finish_init)
    
        def _finish_init(self, dt):
            self.grid_1.cols = 5
            # Loop to make 20 different buttons on screen
            for x in range(15):
                self.buttons.append(Button(text='button{}'.format(x)))
                self.grid_1.add_widget(self.buttons[x])
                self.buttons[x].background_normal = 'star.png'
    
    class MyKivyApp(App):
        def build(self):
            return MyScreenManager()
    
    def main():
        Builder.load_string(kv_text)
        app = MyKivyApp()
        app.run()
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 太棒了,感谢您的回复。所以就 self.ids.grid_1.cols 部分而言——基本上任何 kivy 功能​​都可以以这种方式在 .py 文件中编辑吗?
    • @Austin ,ID 允许您引用任何小部件并在 python 中使用其方法/属性。见kivy.org/docs/guide/…
    • 非常感谢,这是我没有掌握的 kivy 的基本部分。现在,这在很多方面都让事情变得更容易了。
    猜你喜欢
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    相关资源
    最近更新 更多