繁体   English   中英

Kivy:在第二,第三…等屏幕上动态生成按钮

[英]Kivy: Generate dynamically buttons on the second, third… etc screens

我是Kivy的新手:python。 我正在尝试使用ScreenManager做一个应用程序。 我有一个地图地图和地图键的想法应该在几个屏幕上生成按钮。 例如:map:{user1:{thing1:value1,thing2,value2},user2:{thing1:value1 ...}}第一个屏幕在滚动视图中将有两个按钮:user1和user2。 下一个屏幕上的按钮集合将为thing1,thingN,具体取决于用户按下的“ user_name”。 这只是“玩具”项目,我在这里研究Kivy

我有一些全局变量。 在第一个屏幕中,根据用户在第一个屏幕上按下的内容,初始化全局变量“ user_name”。 然后,在第二个屏幕的类中,我尝试使用map_of_maps [user_name] .keys()并将这些键作为按钮放置在第二个屏幕上。

# kivy_test.py

class MyMainApp(App):
    gapi = gAPI("tilit.txt")
    gapi.file_download()
    gapi.parse_downloaded_file()
    global data
    global user_name
    global account
    data = gapi.get_data()
    user_name = None
    account = None
    def build(self):
        return kv

class MainWindow(Screen):
    f_view = ObjectProperty(None)
    def __init__(self,**kwargs):
        super(MainWindow, self).__init__(**kwargs)
        Clock.schedule_once(self.create_scrollview)

    def create_scrollview(self, inst):
        base = data.keys()
        layout = GridLayout(cols=1)
        layout.bind(minimum_height=layout.setter("height"))

        for element in base:
            button = Button(text=str(element), size_hint=(1, 0.1))
            button.bind(on_press=self.on_scrbutton_pressed)
            layout.add_widget(button)
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.f_view.add_widget(scrollview)

    def on_scrbutton_pressed(self, instance):
        user_name = instance.text
        print(instance.text)

class SecondWindow(Screen):
    s_view = ObjectProperty(None)
    def __init__(self,**kwargs):
        super(SecondWindow,self).__init__(**kwargs)
        Clock.schedule_once(self.create_scrollview)

    def create_scrollview(self, inst):
        base = data[user_name].keys() # Here I have a problem
        layout = GridLayout(cols=1)
        layout.bind(minimum_height = layout.setter("height"))

        for element in base:
            button = Button(text = str(element), size_hint=(1,0.1))
            button.bind(on_press=self.on_scrbutton_pressed)
            layout.add_widget(button)
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.s_view.add_widget(scrollview)

    def on_scrbutton_pressed(self, instance):
        print(instance.text)

运行代码时出现错误:base = data [user_name] .keys()。 KeyError:无

# my.kv

# Filename: my.kv
WindowManager:
    MainWindow:
    SecondWindow:
    ThirdWindow:

<MainWindow>:
    name: "main"
    f_view: f_view

    GridLayout:
        cols: 1

        ScrollView:
            id : f_view

#        Button:
#            text: "User1"
#            on_release:
#                app.root.current = "second"
#                root.manager.transition.direction = "left"

#        Button:
#            text: "User2"
#            on_release:
#                app.root.current = "second"
#                root.manager.transition.direction = "left"


<SecondWindow>:
    name: "second"
    s_view : s_view

    GridLayout:
        cols: 1

        ScrollView:
            id : s_view

        Button:
            text: "Add"


<ThirdWindow>:
    name: "third"
    t_view : t_view

    GridLayout:
        cols: 1
        id : t_view

还有一个问题:在这种情况下,如何在屏幕之间执行转换?

问题1-KeyError

     base = data[user_name].keys()  # Here I have a problem
 KeyError: None

根本原因

当Kivy处理您的kv文件时,它将实例化WindowManager对象为根,还实例化其子级MainWindowSecondWindow 在实例化SecondWindow ,它调用了构造函数( __init__ )和方法create_scrollview 它引发了KeyError,因为全局变量user_name包含None的初始值,该初始值在字典类型data中不存在。

在填充user_name之前,在class MainWindow on_scrbutton_pressed方法中添加global user_name user_name 如果没有global user_name ,则将instance.text分配给user_name时,Python将创建一个新的局部变量。

问题2

在这种情况下,如何在屏幕之间执行转换?

  1. 默认情况下,每个屏幕都有一个属性管理器,该管理器为您提供所使用的ScreenManager的实例。 将以下内容添加到class MainWindow on_scrbutton_pressed方法中。

      self.manager.current = "second" self.manager.transition.direction = "left" 
  2. class Secondwindow ,删除构造函数并将方法create_scrollview(self, inst)替换为on_pre_enter(self)
  3. class MainWindow ,将on_pre_enter(self):构造函数__init__替换为on_pre_enter(self):
  4. 添加方法on_pre_leave删除添加的小部件以防止重复

片段

class MainWindow(Screen):
    f_view = ObjectProperty(None)

    def on_pre_enter(self):
        Clock.schedule_once(self.create_scrollview)
    ...

    def on_pre_leave(self):
        self.f_view.clear_widgets()

    def on_scrbutton_pressed(self, instance):
        global user_name
        user_name = instance.text
        print(instance.text)
        self.manager.current = "second"
        self.manager.transition.direction = "left"


class SecondWindow(Screen):
    s_view = ObjectProperty(None)

    def on_pre_enter(self):
        base = data[user_name].keys()
        ...

    def on_pre_leave(self):
        self.s_view.clear_widgets()

我也已经在我的应用程序中实现了几乎相同的功能。

  • 我有一个章节名称列表作为键,其摘要作为值。
  • 当用户进入屏幕时,将调用keys()并创建按钮。
  • 根据单击的按钮,摘要显示在下一个屏幕上

这是我的编码方式(摘要)

class chapter_list(Screen):
    def on_pre_enter(self):
        self.buttons = []
        for i in flamingo.keys(): #for loop to generate buttons
            button = Button(text=str(i),height=150) #the text on the button is the chapter name
            button.bind(on_press=self.pressed) #when the button is clicked, the function pressed on called
            self.ids.fgrid.add_widget(button) #added to the flamingogrid
            self.buttons.append(button)

这里的fgrid是我在kv文件中为此screen选择的Layoutid:在本例中为GridLayout)

self.buttons = []只是为了收集按钮,以便我可以在屏幕出口处将其删除。

让我知道这是否有帮助。

暂无
暂无

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

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