繁体   English   中英

使用On_Press事件来更改没有KV语言的屏幕以动态创建按钮

[英]Use On_Press Event to Change Screen without KV Language for Dynamically Created Buttons

题:

在不使用KV语言的情况下,如何使用On-Press事件更改python中动态创建的按钮的屏幕?

目标:

通过单击动态创建的按钮,可以导航到新屏幕,

[无需在Kivy中创建按钮,并且仍然可以在Python和Kivy中同时使用Screenmanager(不确定在整个程序中是否必须使用Python还是Kivy?)

我已经尝试过的事情:

  1. 使用button_share.bind(on_press = self.changer) ,然后这样做:

def changer(self,*args):
    ScreenManager()
    screenmanager.current = 'MainScreen'

但是我收到错误ScreenManagerException: No Screen with name "MainScreen".

怀疑:

我认为这是因为我正在创建ScreenManager的新实例,而不是引用现有实例。 为了解决这个问题,我考虑在App类中实例化Screenmanager(),然后在我的按钮def changer(self, *args)方法中引用该实例化,但是如果它与我实际上用于所有对象的ScreenManager不同,那将是无用的我的屏幕。 这些都是用KV语言定义的。 如果不付出很大的努力,我将无法将它们全部切换。

  1. 使用:

button_share.bind(on_press=partial(app.sm.setter('current'), (app.sm, "MainScreen")))`

但是我得到的错误是ValueError: ScreenManager.current accept only str

下面是一个完全可运行的示例:

注意:在此示例中,我要单击“继续编辑”按钮,然后单击“测试1”,“测试2”或“测试3”按钮,然后将其带到另一个屏幕。

Python代码:

from kivy.app import App
# kivy.require("1.10.0")
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.uix.widget import Widget
#from kivy.base import runTouchApp
from kivy.properties import StringProperty, ObjectProperty, NumericProperty
from functools import partial

class ScrollableLabelDataEntryInstructions(BoxLayout):
    pass

class NewGarageScreen(Screen):
    pass

class ContinueEditingScreen(Screen):
    pass

class GarageNameBoxLayout(BoxLayout):
    box_share2 = ObjectProperty()
    sm = ScreenManager()

    def __init__(self, **kwargs):
        super(GarageNameBoxLayout, self).__init__(**kwargs)
        self.orientation = "vertical"
        Clock.schedule_interval(self.create_button, 5)

    def create_button(self, *args):
        self.box_share2.clear_widgets()
        app = App.get_running_app()
        #put GarageNameStartList data into app class, then pull from it in this class
        top_button_share = 1.1
        color = (.4, .4, .4, 1)
        for i in range(len(app.GarageNameStartList)):
            top_button_share -= .4
            id_ = app.GarageNameStartList[i]

            button_share = Button(background_normal='',
                                  background_color = color,
                                  id = id_,
                                  pos_hint = {"x": 0, "top": top_button_share},
                                  size_hint_y = None,
                                  height = 60,
                                  font_size = 30,
                                  text = app.GarageNameStartList[i])
            button_share.bind(on_press = self.changer)
            #button_share.bind(on_press=partial(app.sm.setter('current'), (app.sm, "MainScreen")))
            self.box_share2.add_widget(button_share)

    def changer(self,*args):
        ScreenManager()
        #app = App.get_running_app()
        screenmanager.current = 'MainScreen'

class BackHomeWidget(Widget):
    pass

class MainScreen(Screen):
    pass

class AnotherScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("example_on_press.kv")

class MainApp(App):
    GarageNameStartList = ["Test1", "Test2", "Test3"]

    def Update_GarageNameStartList(self, *args):
        self.GarageNameStartList = ["Test1", "Test2", "Test3"]   


    def build(self):
        return presentation

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

验证码:

#: import FadeTransition kivy.uix.screenmanager.FadeTransition

ScreenManagement:
    transition: FadeTransition()
    MainScreen:
    AnotherScreen:
    NewGarageScreen:
    ContinueEditingScreen:

<SmallNavButton@Button>:    
    font_size: 32
    size: 125, 50    
    color: 0,1,0,1

<MedButton@Button>:
    font_size: 30
    size_hint: 0.25, 0.1
    color: 0,1,0,1

<BackHomeWidget>:
    SmallNavButton:
        on_release: app.root.current = "main"
        text: "Home"
        pos: root.x, root.top - self.height

<MainScreen>:
    name: "main"
    FloatLayout: 
        MedButton:
            on_release: app.root.current = "edit"
            text: "Edit"
            pos_hint: {"x":0.3728, "top": 0.4}

<AnotherScreen>:
    name: "edit"
    BackHomeWidget:
        SmallNavButton:
            on_release: app.root.current = "main"
            text: "Back"
            pos: root.x, root.top - (2.25*(self.height))
    FloatLayout:
        MedButton:
            on_release: app.root.current = "continueediting"
            text: "Continue Editing"
            pos_hint: {"x":0.25, "top": 0.6} 
        MedButton:
            on_release: app.root.current = "newgarage"
            text: "Create New"
            pos_hint: {"x":0.3728, "top": 0.4}

<NewGarageScreen>:
    name: "newgarage"
    BackHomeWidget:
        SmallNavButton:
            on_release: app.root.current = "edit"
            text: "Back"
            pos: root.x, root.top - (2.25*(self.height))
    FloatLayout:
        MedButton:
            text: "1. Groundfloor"
            pos_hint: {"x":0, "top": 0.6}


<GarageNameBoxLayout>:
    box_share2: box_share2
    ScrollView:
        GridLayout:
            id: box_share2
            cols: 1
            size_hint_y: None
            size_hint_x: 0.5
            spacing: 5
            padding: 130
            height: self.minimum_height
            canvas:
                Color: 
                    rgb: 0, 0, 0
                Rectangle:
                    pos: self.pos
                    size: self.size         

<ContinueEditingScreen>:
    name: "continueediting"
    GarageNameBoxLayout:
    BackHomeWidget:
        SmallNavButton:
            on_release: app.root.current = "edit"
            text: "Back"
            pos: root.x, root.top - (2.25*(self.height))

您的代码可以在以下方面进行改进:

  • 您不必在.py中创建box_share2,因为您是在.kv中创建它的

  • 当您使用sm = ScreenManager()您将创建另一个不同于原始ScreenManager ,这不是必需的。

  • 不必使用rangelen ,使代码的可读性降低,您只需进行迭代即可。

  • 如果我们查看.kv的结构,我们会看到演示对象是ScreenManager因此可以通过app.root获取它。

使用上面的代码,解决方案是:

[...]

class GarageNameBoxLayout(BoxLayout):
    def __init__(self, **kwargs):
        super(GarageNameBoxLayout, self).__init__(**kwargs)
        self.orientation = "vertical"
        Clock.schedule_interval(self.create_button, 5)

    def create_button(self, *args):
        self.box_share2.clear_widgets()
        app = App.get_running_app()
        sm = app.root

        #put GarageNameStartList data into app class, then pull from it in this class
        top_button_share = 1.1
        color = (.4, .4, .4, 1)
        for text in app.GarageNameStartList:
            top_button_share -= .4
            id_ = text
            button_share = Button(background_normal='',
                                  background_color = color,
                                  id = id_,
                                  pos_hint = {"x": 0, "top": top_button_share},
                                  size_hint_y = None,
                                  height = 60,
                                  font_size = 30,
                                  text = text)
            button_share.bind(on_press=lambda *args: setattr(sm, 'current', "main"))
            self.box_share2.add_widget(button_share)

[...]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM