Kivy:在第二个,第三个...等屏幕上动态生成按钮
Kivy: Generate dynamically buttons on the second, third... etc screens
我是基维新人:python。我正在尝试使用 ScreenManager 做一个应用程序。我有地图的地图和地图的键的想法应该在多个屏幕上生成按钮。例如:
地图:{user1:{thing1:value1,thing2,value2},user2:{thing1:value1 ...}}
第一个屏幕将在滚动视图中有两个按钮:user1 和 user2。
下一个屏幕上的按钮集合将是 thing1,thingN,具体取决于 "user_name" 用户按下的内容。这只是"toy"项目,我正在研究Kivy
我有一些全局变量。在第一个屏幕中,全局变量 "user_name" 根据用户在第一个屏幕上按下的内容进行初始化。然后在第二个屏幕的 class 中,我尝试使用 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()。键错误:None
# 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
对象实例化为根对象,并且还会实例化其子对象 MainWindow
和 SecondWindow
。在实例化 SecondWindow
时,它调用了构造函数 (__init__
) 和方法 create_scrollview
。它抛出一个 KeyError 因为全局变量 user_name
包含 None
的初始值,它在字典类型 data
.
中不存在
解决方案
在填充 user_name
之前,在 class MainWindow
的方法 on_scrbutton_pressed
中添加 global user_name
。如果没有 global user_name
,Python 会在 instance.text
分配给 user_name
时创建一个新的局部变量。
问题 2
How to perform transitions between screens in this case?
解决方案
默认情况下,每个屏幕都有一个 属性 管理器,它为您提供
使用的 ScreenManager 的实例。在方法中添加以下内容
on_scrbutton_pressed
个 class MainWindow
。
self.manager.current = "second"
self.manager.transition.direction = "left"
- 在
class Secondwindow
中,删除构造函数并将方法 create_scrollview(self, inst)
替换为 on_pre_enter(self)
- 在
class MainWindow
中,将构造函数 __init__
替换为 on_pre_enter(self):
- 添加方法
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
是 Layout
的 id:
(在本例中为 GridLayout)我在 kv
文件中为此 screen
选择
self.buttons = []
只是为了收集按钮,以便我可以在屏幕退出时删除它们。
让我知道这是否有帮助。
我是基维新人:python。我正在尝试使用 ScreenManager 做一个应用程序。我有地图的地图和地图的键的想法应该在多个屏幕上生成按钮。例如: 地图:{user1:{thing1:value1,thing2,value2},user2:{thing1:value1 ...}} 第一个屏幕将在滚动视图中有两个按钮:user1 和 user2。 下一个屏幕上的按钮集合将是 thing1,thingN,具体取决于 "user_name" 用户按下的内容。这只是"toy"项目,我正在研究Kivy
我有一些全局变量。在第一个屏幕中,全局变量 "user_name" 根据用户在第一个屏幕上按下的内容进行初始化。然后在第二个屏幕的 class 中,我尝试使用 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()。键错误:None
# 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
对象实例化为根对象,并且还会实例化其子对象 MainWindow
和 SecondWindow
。在实例化 SecondWindow
时,它调用了构造函数 (__init__
) 和方法 create_scrollview
。它抛出一个 KeyError 因为全局变量 user_name
包含 None
的初始值,它在字典类型 data
.
解决方案
在填充 user_name
之前,在 class MainWindow
的方法 on_scrbutton_pressed
中添加 global user_name
。如果没有 global user_name
,Python 会在 instance.text
分配给 user_name
时创建一个新的局部变量。
问题 2
How to perform transitions between screens in this case?
解决方案
默认情况下,每个屏幕都有一个 属性 管理器,它为您提供 使用的 ScreenManager 的实例。在方法中添加以下内容
on_scrbutton_pressed
个class MainWindow
。self.manager.current = "second" self.manager.transition.direction = "left"
- 在
class Secondwindow
中,删除构造函数并将方法create_scrollview(self, inst)
替换为on_pre_enter(self)
- 在
class MainWindow
中,将构造函数__init__
替换为on_pre_enter(self):
- 添加方法
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
是 Layout
的 id:
(在本例中为 GridLayout)我在 kv
文件中为此 screen
选择
self.buttons = []
只是为了收集按钮,以便我可以在屏幕退出时删除它们。
让我知道这是否有帮助。