【问题标题】:Infinitely animating a label in Kivy - "On change screen"在 Kivy 中无限地为标签设置动画 - “在更改屏幕上”
【发布时间】:2020-12-26 22:35:57
【问题描述】:

我想为我的吉他练习制作一个快速肮脏的应用程序(为什么不呢?)并决定在没有任何 Kivy 经验的情况下使用 Kivy。这是一个非常简单的应用程序(代码写得非常糟糕),有两个屏幕和一系列可供迭代的和弦。用户选择他想要练习的和弦(ToggleButtons),然后这些和弦在点击“接受”按钮时会在用户给定的时间间隔在第二个屏幕上迭代动画。

但是,我遇到了用和弦在第二个屏幕上为“无限变化的标签”设置动画的麻烦。我该怎么做呢?另外,如何将值(用户选择的和弦和分钟)从第一个屏幕传递到第二个屏幕的标签?

非常感谢任何帮助。希望解决方案对于有 Kivy 经验的人来说应该很容易。这是我的看法(无法正常工作):

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.animation import Animation
from kivy.clock import Clock

class MyGrid(GridLayout):
    def __init__(self, **kwargs):
        super(MyGrid, self).__init__(**kwargs)
        self.sel_chords = []
        self.time = 0
        
        self.cols = 1
        self.add_widget(Label(text="Please, select the chords you would like to practise."))

        self.intro = StackLayout()

        self.A = ToggleButton(text = "A", size_hint=(.2,.2))
        self.intro.add_widget(self.A)

        self.E = ToggleButton(text = "E", size_hint=(.2,.2))
        self.intro.add_widget(self.E)
        
        self.C = ToggleButton(text = "C", size_hint=(.2,.2))
        self.intro.add_widget(self.C)
                
        self.D = ToggleButton(text = "D", size_hint=(.2,.2))
        self.intro.add_widget(self.D)
                
        self.G = ToggleButton(text = "G", size_hint=(.2,.2))
        self.intro.add_widget(self.G)
                
        self.Cadd9 = ToggleButton(text = "Cadd9", size_hint=(.2,.2))
        self.intro.add_widget(self.Cadd9)
        self.add_widget(self.intro)
        
        self.outro = GridLayout(cols=3)
        self.outro.add_widget(Label(text="Seconds per chord:"))
        self.minutes = TextInput(multiline=False)
        self.outro.add_widget(self.minutes)
        self.submit = Button(text="Accept", font_size=40)
        self.submit.bind(on_press=self.pressed)
        self.outro.add_widget(self.submit)
        self.add_widget(self.outro)

    def pressed(self, instance):
        if self.A.state == "down":
            self.sel_chords.append("A")
        if self.C.state == "down":
            self.sel_chords.append("C")
        if self.D.state == "down":
            self.sel_chords.append("D")
        if self.E.state == "down":
            self.sel_chords.append("E")
        if self.G.state == "down":
            self.sel_chords.append("G")
        if self.Cadd9.state == "down":
            self.sel_chords.append("Cadd9")
        try:
            self.time = int(self.minutes.text)
        except:
            pass
        
        print(self.time)
        self.time = 0
        self.sel_chords = []

class MyGrid2(GridLayout):
    def __init__(self, **kwargs):
        super(MyGrid2, self).__init__(**kwargs)
        self.cols = 1
        self.rows = 2
        self.temp = "A"
        self.lbl = Label(text="A")
        self.lbl.font_size = '300dp'
        self.add_widget(self.lbl)
        self.back = Button(text="Back", font_size=40)
        self.add_widget(self.back)
        #for element in itertools.cycle(["A", "B"]):
        #   self.lbl.text = element
        def update_lbl(time):
            pass #update lbl to the chords
        Clock.schedule_interval(update_lbl, 1)
        
class MyScreenManager(ScreenManager):
    def __init__(self, **kwargs):
        super(MyScreenManager, self).__init__(**kwargs)

        self.main_screen = Screen(name="main_screen")
        self.new_screen = Screen(name="new_screen")

        self.add_widget(self.main_screen)
        self.add_widget(self.new_screen)

        main_grid = MyGrid()
        main_grid.submit.bind(on_press=self.next_screen)
        self.main_screen.add_widget(main_grid)
        
        next_grid = MyGrid2()
        next_grid.back.bind(on_press=self.back_screen)
        self.new_screen.add_widget(next_grid)
        
    def next_screen(self, *args):
        self.current = "new_screen"   
        
    def back_screen(self, *args):
        self.current = "main_screen" 

class MyApp(App):
    def build(self):
        return MyScreenManager()


if __name__ == "__main__":
    MyApp().run()

【问题讨论】:

  • 可能screen 应该可以通过self.parent 访问ScreenManager,然后它可以使用self.parent.main_screen 访问其他屏幕
  • update_lbl 中,您可以使用一些变量来计算它执行了多少次 - 即。 self.frame - 将此值与if/else 一起使用,您可以决定在标签中更改什么。

标签: python kivy kivy-language


【解决方案1】:

我尽量不要过多地更改您的代码。

因此,与您最初离开的地方分开,我使用按钮 Accept 来初始化您的 next_scren 中的标签更改。用它我们调用一个函数start传递选择的按钮列表和时间,并使用这两个值来更新标签。

对于这次更新,我们可以使用另一个函数来安排一个时钟间隔来决定哪个是下一个按钮。

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.animation import Animation
from kivy.clock import Clock


class MyGrid(GridLayout):
    def __init__(self, **kwargs):
        super(MyGrid, self).__init__(**kwargs)
        self.sel_chords = []
        self.time = 0

        self.cols = 1
        self.add_widget(Label(text="Please, select the chords you would like to practise."))

        self.intro = StackLayout()

        self.A = ToggleButton(text="A", size_hint=(.2, .2))
        self.intro.add_widget(self.A)

        self.E = ToggleButton(text="E", size_hint=(.2, .2))
        self.intro.add_widget(self.E)

        self.C = ToggleButton(text="C", size_hint=(.2, .2))
        self.intro.add_widget(self.C)

        self.D = ToggleButton(text="D", size_hint=(.2, .2))
        self.intro.add_widget(self.D)

        self.G = ToggleButton(text="G", size_hint=(.2, .2))
        self.intro.add_widget(self.G)

        self.Cadd9 = ToggleButton(text="Cadd9", size_hint=(.2, .2))
        self.intro.add_widget(self.Cadd9)
        self.add_widget(self.intro)

        self.outro = GridLayout(cols=3)
        self.outro.add_widget(Label(text="Seconds per chord:"))
        self.minutes = TextInput(multiline=False)
        self.outro.add_widget(self.minutes)
        self.submit = Button(text="Accept", font_size=40)
        self.submit.bind(on_press=self.pressed)
        self.outro.add_widget(self.submit)
        self.add_widget(self.outro)

    def pressed(self, instance):
        self.sel_chords =[]

        if self.A.state == "down":
            self.sel_chords.append("A")
        if self.C.state == "down":
            self.sel_chords.append("C")
        if self.D.state == "down":
            self.sel_chords.append("D")
        if self.E.state == "down":
            self.sel_chords.append("E")
        if self.G.state == "down":
            self.sel_chords.append("G")
        if self.Cadd9.state == "down":
            self.sel_chords.append("Cadd9")
        try:
            self.time = int(self.minutes.text) * 60
        except:
            self.time = 60

        next_screen = App.get_running_app().root.get_screen("new_screen").children[0]
        next_screen.start(self.sel_chords, self.time)


class MyGrid2(GridLayout):
    def __init__(self, **kwargs):
        super(MyGrid2, self).__init__(**kwargs)
        self.cols = 1
        self.rows = 2
        self.temp = "A"
        self.lbl = Label(text="A")
        self.lbl.font_size = '300dp'
        self.add_widget(self.lbl)
        self.back = Button(text="Back", font_size=40)
        self.add_widget(self.back)

        self.selected_buttons = None

    def start(self, button_list, time):
        if len(button_list) == 0:
            return
        self.selected_buttons = button_list
        self.lbl.text = self.selected_buttons[0]
        Clock.schedule_interval(lambda x: self.update_lbl(self.next_button()), time)

    def next_button(self):
        if self.selected_buttons.index(self.lbl.text) == len(self.selected_buttons) - 1:
            return 0
        else:
            return self.selected_buttons.index(self.lbl.text) + 1

    def update_lbl(self, button, *kwargs):
        self.lbl.text = self.selected_buttons[button]


class MyScreenManager(ScreenManager):
    def __init__(self, **kwargs):
        super(MyScreenManager, self).__init__(**kwargs)

        self.main_screen = Screen(name="main_screen")
        self.new_screen = Screen(name="new_screen")

        self.add_widget(self.main_screen)
        self.add_widget(self.new_screen)

        main_grid = MyGrid()
        main_grid.submit.bind(on_press=self.next_screen)
        self.main_screen.add_widget(main_grid)

        next_grid = MyGrid2()
        next_grid.back.bind(on_press=self.back_screen)
        self.new_screen.add_widget(next_grid)

    def next_screen(self, *args):
        self.current = "new_screen"

    def back_screen(self, *args):
        self.current = "main_screen"



class MyApp(App):
    def build(self):
        return MyScreenManager()


if __name__ == "__main__":
    MyApp().run()

现在由您根据自己的需要来完善和更改此代码。

【讨论】:

  • 完美!浏览了您的添加内容,这很有意义:) 我在不同屏幕之间传递信息时遇到了麻烦,但这绝对解决了问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多