重定向

时间:2017-03-19 02:25:21

标签: python kivy

我正在尝试使用kivy开发一个应用程序来注册锻炼程序,在屏幕管理器中有几个屏幕。但是,在运行代码时,我得到一个ScreenManagerException:

kivy.uix.screenmanager.ScreenManagerException: No Screen with name "('Suplementos', <kivy.uix.button.Button object at 0xb3d3341c>)".

该应用程序目前由以下代码片段组成(python 2.7 + kivy 1.9):

main.py

#coding:utf-8

from functools import partial
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.scrollview import ScrollView

import time

class TelaInicial(Screen):
    layout_telainicial = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(TelaInicial, self).__init__(**kwargs)

        opcoes = [
                'Suplementos',
                'Cardiovascular',
                'Novo treino'
                ]

        for opt in opcoes:
            Opcao = Button(
                            text=str(opt), 
                            size_hint_y=None, 
                            height=60,
                            )
            Opcao.bind(on_press=partial(self.ir_para, opt))

            self.ids.layout_telainicial.add_widget(Opcao)

    def ir_para(self, *args):
        self.parent.current = str(args)


class Suplementos(Screen): 
    layout_suplementos = ObjectProperty(None)

    def __init__(self, **kwargs):
        hora = time.asctime()
        super(Suplementos, self).__init__(**kwargs)
        mostrar_hora = Label(text=str(hora))
        self.ids.layout_suplementos.add_widget(mostrar_hora)

class Cardiovascular(Screen):
    layout_cardiovascular = ObjectProperty(None)

    def __init__(self, **kwargs):
        hora = time.asctime()
        super(Cardiovascular, self).__init__(**kwargs)
        mostrar_hora = Label(text=str(hora))
        self.ids.layout_cardiovascular.add_widget(mostrar_hora)

class NovoTreino(Screen):
    layout_novotreino = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(NovoTreino, self).__init__(**kwargs)

        AdicionarExercicio = Button(
                                    text='+', 
                                    size_hint_y=None, 
                                    height=60,
                                    )
        AdicionarExercicio.bind(on_press=lambda a: self.NovoExercicio)

        self.ids.layout_novotreino.add_widget(AdicionarExercicio)

    def NovoExercicio(self, *args):
        self.parent.current = 'Seleção de exercícios'

class SelecaoExercicio(Screen):
    pass

class GerenciadorApp(App):
    def build(self):
        MyScreenManager = ScreenManager()
        MyScreenManager.add_widget(TelaInicial())
        MyScreenManager.add_widget(Suplementos())
        MyScreenManager.add_widget(Cardiovascular())
        MyScreenManager.add_widget(NovoTreino())
        MyScreenManager.add_widget(SelecaoExercicio())
        return MyScreenManager

GerenciadorApp().run()

gerenciador.kv

<TelaInicial>
    name: 'Tela inicial'
    ScrollView:
        GridLayout:
            id: layout_telainicial
            cols: 1
            padding: 10
            spacing: 10
            size_hint: 1, None
            height: self.minimum_height

<Suplementos>
    name: 'Suplementos'
    ScrollView:
        GridLayout:
            id: layout_suplementos
            cols: 1
            padding: 10
            spacing: 10
            size_hint: 1, None
            height: self.minimum_height
            Label:
                text: 'Registro de suplementos'

<Cardiovascular>
    name: 'Cardiovascular'
    ScrollView:
        GridLayout:
            id: layout_cardiovascular
            cols: 1
            padding: 10
            spacing: 10
            size_hint: 1, None
            height: self.minimum_height
            Label:
                text: 'Exercício cardiovascular'

<NovoTreino>
    name: 'Novo treino'
    ScrollView:
        GridLayout:
            id: layout_novotreino
            cols: 1
            padding: 10
            spacing: 10
            size_hint: 1, None
            height: self.minimum_height
            Label:
                text: 'Treino de musculação'

<SelecaoExercicio>
    name: 'Seleção de exercícios'
    ScrollView:
        GridLayout:
            id: layout_selecaoexercicios
            cols: 1
            padding: 10
            spacing: 10
            size_hint: 1, None
            height: self.minimum_height

在以前版本的代码中,我还尝试了一个lambda函数而不是partial()函数,在TelaInicial类构造函数中使用它来绑定“on_press”按钮的属性:

class TelaInicial(Screen):
    layout_telainicial = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(TelaInicial, self).__init__(**kwargs)

        opcoes = [
                'Suplementos',
                'Cardiovascular',
                'Novo treino'
                ]

        for opt in opcoes:
            Opcao = Button(
                            text=str(opt), 
                            size_hint_y=None, 
                            height=60,
                            )
            Opcao.bind(on_press=self.ir_para(opt))

            self.ids.layout_telainicial.add_widget(Opcao)

    def ir_para(self, destino, *args):
        self.parent.current = str(destino)

对于所有按钮,这将始终返回选项列表中的最后一个屏幕'NovoTreino',而不是每个按钮标识的屏幕。

为什么代码不能在每种情况下工作 - 我怎么能解决它?

1 个答案:

答案 0 :(得分:1)

问题是当你只想要第一项args时,你将screenmanagers设置为整个args列表。

>>> print(args)
('Suplementos', <kivy.uix.button.Button object at 0xb3d3341c>)
>>> print(args[0])
'Suplementos'

所以你需要的是:

def ir_para(self, *args):
    self.parent.current = str(args[0])