【问题标题】:Kivy: I want to change an attribute (e.g. text) of a widget by means of another widget (e.g. button) on clickKivy:我想通过单击另一个小部件(例如按钮)来更改小部件的属性(例如文本)
【发布时间】:2016-12-20 11:12:34
【问题描述】:

我对 Kivy 完全陌生,想要将屏幕管理器从一个屏幕转换到另一个屏幕。我不知道如何在按钮的 on_press 方法中访问屏幕管理器的属性。

到目前为止,这是我的代码:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.button import Button
from kivy.uix.label import Label

class ScreenButton(Button):
    def __init__(self):
        super(Button, self).__init__()
        self.text = "Press Me!"

    def on_press(self, *args):
        sm.current = 'secondscreen'

class MainApp(App):
    def build(self):
        sm = ScreenManager()
        sm.transition = FadeTransition()

        sc1 = Screen(name='firstscreen')
        sc1.add_widget(ScreenButton())

        sc2 = Screen(name='secondscreen')
        sc2.add_widget(Label(text='Another screen!'))

        sm.add_widget(sc1)
        sm.add_widget(sc2)

        return sm

MainApp().run()

我了解,此代码不起作用,因为 sm 未在按钮的方法中定义。但是,例如,如何访问按钮的类定义中的特定小部件?或者有没有更优雅的方式来设置小部件之间的通信以通过彼此改变它们的条件?

感谢您的帮助。

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    您也可以将 sm (ScreenManager) 作为 kwarg 传递(请参阅###)。这样您就可以重用 ScreenButton 而不必使用全局。

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
    from kivy.uix.button import Button
    from kivy.uix.label import Label
    
    class ScreenButton(Button):
    
       def __init__(self, **kwargs): ###
           super(ScreenButton, self).__init__()
    
           self.manager = kwargs.pop('manager', None) ### 
           self.text = "Press Me!"
    
       def on_press(self, *args):
    
           self.manager.current = 'secondscreen' ###
    
    
    class MainApp(App):
        def build(self):
    
            sm = ScreenManager()
    
            sm.transition = FadeTransition()
    
            sc1 = Screen(name='firstscreen')
            sc1.add_widget(ScreenButton(manager=sm)) ###
    
            sc2 = Screen(name='secondscreen')
            sc2.add_widget(Label(text='Another screen!'))
    
            sm.add_widget(sc1)
            sm.add_widget(sc2)
    
            return sm
    
    MainApp().run()
    

    【讨论】:

    • 这行得通!我不明白的是,通过这一行: self.manager = kwargs.pop('manager', None) 我正在按钮类中创建另一个anager,对吗?怎么,通过改变 self.manager 的状态,我也改变了外部定义的 sm 的状态?问候
    • 因为 self.manager 是 sm(或者至少也是一个参考)。 'kwargs.pop('manager', None)' 就像说有一个名为“manager”的关键字可能会传递给这个类,如果是,那么 self.manager 指的是那个(如果不是,self.manager值为无)。在这种情况下,当您创建 ScreenButton(manager=sm) 时,您将 sm 的“值”传递给成为 self.manager 的关键字管理器......这有什么意义吗?
    【解决方案2】:

    在您的示例中执行此操作的一种方法是将sm 设为全局:

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
    from kivy.uix.button import Button
    from kivy.uix.label import Label
    
    class ScreenButton(Button):
        def __init__(self):
            super(ScreenButton, self).__init__()
            self.text = "Press Me!"
    
        def on_press(self, *args):
            sm.current = 'secondscreen'
    
    
    sm = ScreenManager()
    
    
    class MainApp(App):
        def build(self):
            sm.transition = FadeTransition()
    
            sc1 = Screen(name='firstscreen')
            sc1.add_widget(ScreenButton())
    
            sc2 = Screen(name='secondscreen')
            sc2.add_widget(Label(text='Another screen!'))
    
            sm.add_widget(sc1)
            sm.add_widget(sc2)
    
            return sm
    
    MainApp().run()
    

    【讨论】:

      【解决方案3】:

      好的,我有一个完全不同的解决方案,而且它需要的工作量要少得多。您将需要 2 个文件,main.py 和screens.kv

      这里是 main.py:

      import kivy
      kivy.require('1.10.0')
      from kivy.app import App
      from kivy.uix.screenmanager import Screen, ScreenManager, FadeTransition
      from kivy.uix.button import Button
      from kivy.uix.label import Label
      from kivy.uix.gridlayout import GridLayout
      
      class Manager(ScreenManager):
          pass
      
      class FirstScreen(Screen):
          pass
      
      class SecondScreen(Screen):
          pass
      
      class ScreensApp(App):
          def build(self):
              return Manager()
      
      if __name__ == '__main__':
          ScreensApp().run()
      

      还有screens.kv:

      #: import sm kivy.uix.screenmanager
      
      <Manager>
          transition: sm.FadeTransition()
          FirstScreen:
          SecondScreen:
      
      <FirstScreen>
          name: 'First'
          GridLayout:
              Label:
                  text: "First Screen"
              Button:
                  text: "Press Me!"
                  on_release: app.root.current = 'Second'
      
      <SecondScreen>
          name: 'Second'
          GridLayout:
              Label:
                  text: "Second Screen"
              Button:
                  text: "Press Here!"
                  on_release: app.root.current = 'First'
      

      希望这会有所帮助。

      【讨论】:

      • 使用 .kv 文件更容易,因为随着您的代码变得越来越复杂,将所有小部件保持有序会更容易。同样在 .py 文件中,您必须手动添加所有小部件,而在 kv 文件中,您只需要引用它们。您可以在 kivy.org/docs 找到所需的一切
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多