倒计时/计时器在 kivy/python 中更改屏幕

Posted

技术标签:

【中文标题】倒计时/计时器在 kivy/python 中更改屏幕【英文标题】:Countdown/timer to change screen in kivy/python 【发布时间】:2020-05-05 10:26:26 【问题描述】:

我想做的是在第一个屏幕上显示 2 秒钟的图像,然后切换到另一个屏幕。

我尝试使用来自 kivy 的 Clock,我认为它可以正常工作,但我收到错误消息:

self.parent.current = "tela_01" 
AttributeError: 'float' object has no attribute 'parent'

我想我写错了接下来要访问的屏幕部分。我看到了一堆关于屏幕管理器的答案、视频和教程,但没有任何效果,我不知道我做错了什么。可能是因为我对这门语言和学习还很陌生,但似乎很简单。

为了测试我是否可以转到所有屏幕,我为有问题的屏幕创建了一个按钮(在代码中进行了注释),但我想要一个计时器/倒计时之类的东西来改变屏幕。

.py

import kivy

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import FontContextManager
from kivy.uix.scrollview import ScrollView
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock
from kivy.uix.image import Image
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Color

#---Screen Manager
class Gerenciador_Telas(ScreenManager):
    pass

#---Opening
class Tela_00(Screen):
#self.parent is the equivalent to app.root
    def switch(self):
        self.parent.current = "tela_01"

    Clock.schedule_once(switch, 2)

#---First Screen
class Tela_01(Screen):
    pass

#---Names Screen
class Tela_02(Screen):

#Save names
    e1n1 = ObjectProperty(None)
    e1n2 = ObjectProperty(None)
    e2n1 = ObjectProperty(None)
    e2n2 = ObjectProperty(None)

    def button(self):
        print(
               "Equipe 1A:", self.e1n1.text,
               "Equipe 1B:", self.e1n2.text,
               "Equipe 2A:", self.e2n1.text,
               "Equipe 2B:", self.e2n2.text
               )
#Clear names
        self.e1n1.text = ""
        self.e1n2.text = ""
        self.e2n1.text = ""
        self.e2n2.text = ""

    pass


#---Score
class Tela_03(Screen):
    pass

#---Add Score
class Tela_04(Screen):
    pass

#---Rules
class Tela_05(Screen):
    pass

#---Run App
iniciar = Builder.load_file("pontos_tranca.kv")

class Pontos_Tranca(App):
    def build(self):
        return iniciar

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

.kv

#:import Clock kivy.clock.Clock

Gerenciador_Telas:
    Tela_00:
    Tela_01:
    Tela_02:
    Tela_03:
    Tela_04:
    Tela_05:

<Tela_00>
    name: "tela_00"

    BoxLayout:
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: self.pos
                size: self.size
        Image:
            source: "inicial.png"

#    FloatLayout:
#
#        Button:
#            text: "Próximo"
#            background_normal: ""
#            background_color: 0,0,0,1
#            size_hint: .2, .1
#            pos: 325, 50
#            on_release:
#                app.root.current = "tela_01"
#                root.manager.transition.direction = "left"


<Tela_01>
    name: "tela_01"

    GridLayout:
        cols: 1
        size: root.width, root.height
        padding: 200
        spacing: 20

        Label:
            text: "Pontos de Tranca 2.0"

        Button:
            text: "Novo"
            on_release:
                app.root.current = "tela_02"
                root.manager.transition.direction = "left"

        Button:
            text: "Continuar"

        Button:
            text: "Regras"
            on_release:
                app.root.current = "tela_05"
                root.manager.transition.direction = "left"

<Tela_02>
    name: "tela_02"

    e1n1: e1n1
    e1n2: e1n2
    e2n1: e2n1
    e2n2: e2n2

    GridLayout:
        cols: 1
        size: root.width, root.height
        padding: 200, 50, 200, 50
        spacing: 10


        Label:
            text: "Equipe 01"

        TextInput:
            multiline: False
            id: e1n1
        TextInput:
            multiline: False
            id: e1n2


        Label:
            text: "Equipe 02"


        TextInput:
            multiline: False
            id: e2n1
        TextInput:
            multiline: False
            id: e2n2

        Button:
            text: "Prosseguir"
            on_press: root.button()
            on_release:
                app.root.current = "tela_01" if e1n1.text and e1n2.text and e2n1.text and e2n2.text != "" else "tela_03"
                root.manager.transition.direction = "right"

<Tela_03>
    name: "tela_03"

<Tela_04>
    name: "tela_04"

<Tela_05>
    name: "tela_05"

    AnchorLayout:
        padding: 100
        anchor_x: "center"
        anchor_y: "top"

        Label:
            text_size: self.width, None
            text: str("Tranca pode ser jogado um com o outro ou em dupla. São distribuídas 11 cartas para cada jogador, e separados 2 montes de 11 para os mortos, um para cada equipe. O morto é um conjunto de cartas que só podem ser utilizado caso algum jogador da equipe acabe com as cartas de sua mão. Para iniciar uma partida, o primeiro jogador à direita de quem deu as cartas compra uma carta do monte que sobrou e verifica se tem interesse. Caso não queira a carta comprada, ele pode descartar e comprar outra. Para as demais rodadas, o jogador seguinte pode comprar uma carta no monte ou pegar todas as cartas da lixeira, desde que justifique a compra da carta de cima, encaixando-a diretamente em um jogo na mesa, ou juntando com duas cartas ou mais da mão e baixando como um novo jogo. Caso a primeira carta da lixeira seja um 3 preto, não é possível comprá-la, pois essas cartas trancam a mesa. Após o início de cada rodada, o jogador poderá baixar uma combinação de cartas, sendo no mínimo")

    FloatLayout:
        size_hint: .2, .1
        pos: 200, 50

        Button:
            text: "Menu"
            on_release:
                app.root.current = "tela_01"
                root.manager.transition.direction = "right"

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

您可以使用on_enter 事件来启动您的Clock 计时器,方法是向您的Tela_00 类添加on_enter() 方法:

class Tela_00(Screen):
#self.parent is the equivalent to app.root
    def switch(self, *args):
        self.parent.current = "tela_01"

    def on_enter(self, *args):
        # called when this Screen is displayed
        Clock.schedule_once(self.switch, 2)

【讨论】:

【参考方案2】:
class Tela_00(Screen):
#self.parent is the equivalent to app.root
    def switch(self):
        self.parent.current = "tela_01"

    Clock.schedule_once(switch, 2)

因为您在任何方法或函数之外编写了Clock.schedule_once,所以它会在创建类时立即执行。它会自动将参数传递给switch,这是一个浮点数,表示自调度以来的时间。您已将该参数命名为 self。因此,self.parent 因您看到的原因无效。

您需要在应用程序控制流中进行时钟调度,调度该类的某个实例的switch 方法。

【讨论】:

感谢您的解释。我做了缩进更正,但它仍然不起作用。错误消失了,但 2 秒后屏幕没有变化。

以上是关于倒计时/计时器在 kivy/python 中更改屏幕的主要内容,如果未能解决你的问题,请参考以下文章

iOS中都有哪些倒计时App可以在锁屏时显示?

开学倒计时!鑫飞教学一体机,开启“屏”教学时代

在 Swift 中更改计时器选择器函数中的 userInfo

SwiftUI:具有计时器样式的文本在提供的日期更改后不会更新

ipod中,写计时器倒计时界面倒计时没有更改

利用ASP技术做网页计时器