生成GUI后,如何在kivy中创建带参数的按钮循环?
How to create an buttonloop with parameter in kivy, after the GUI has generated?
我对 Kivy-Libaray 有疑问。我目前正在为 ShoppinglistApp 编写前端。我有一个主菜单,在那里你可以 select 你想做什么(添加列表/商店)从那里你可以到达商店 selection.
- 在商店 selection 菜单中有 4 家商店。
- 所有项目(产品)都存储在列表中。
- 如果您 select 商店,则应为(来自该商店的)每个商品创建一个按钮。
我厌倦了这个解决方案:
from kivy.app import App
from kivy.metrics import dp
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.stacklayout import StackLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
# the rest
class Produkt:
def __init__(self, name, amount, market):
self.name = name
self.amount = amount
self.market = market
eklist = []
for i in range(0, 100):
nn = "Banane" + str(i)
eklist.append(Produkt(nn, 0, "Baumarkt"))
# Define Screens
class FirstWindow(Screen):
pass
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
"""Anfang der Chose"""
class Box(BoxLayout):
pass
# Gvar is a class I created for the purpose of transporting variable(s). Especially the selected shop.
class Gvar:
def __init__(self, var1):
self.var1 = var1
def get(self):
return self.var1
gvar = Gvar("default")
# SetBox ist the Class for changing the variable through the shop selection menu.
class SetBox(BoxLayout):
def set(self, market):
gvar.var1 = market
print("Set")
print(gvar.var1)
class BLE(BoxLayout):
pass
# This is the Menus which makes Problems.
class SLE(StackLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for p in eklist:
# In theory, this if request should always be triggerd. In praxis, I made the else Request to debug.
# for Text normally would appear p.name, but I changed it for debugging. Text shown(gvar.var1) is "default".
if p.market == str(gvar.get()):
b = Button(text=str(gvar.get()), size_hint=(None, None), color="blue", size=(dp(200), dp(100)),
on_press=lambda *args: self.test1(*args, str(p.name)))
b.prod = p
self.add_widget(b)
else:
b = Button(text=str(gvar.get()), size_hint=(None, None), color="green", size=(dp(200), dp(100)),
on_press=lambda *args: self.test1(*args, str(p.name)))
b.prod = p
self.add_widget(b)
market = None
# test 1 is a placeholder for a Backend funktion
# Here I print the Produkt and gvar.var1, to debug. Here it get for gvar.var1 the in the GUI selected Value.
def test1(self, b, i):
print("Initialize test2, please wait...")
print(b.prod.name, b.prod.amount, b.prod.market, gvar.var1)
"""Ende der Chose"""
kv = Builder.load_file('einkaufsliste.kv')
class EinkaufsApp(App):
def build(self):
return kv
if __name__ == '__main__':
EinkaufsApp().run()
+
这是 Kivy 文件。
WindowManager:
FirstWindow:
SecondWindow:
ThirdWindow:</p>
<FirstWindow>:
name: "first"
Box:
orientation: "vertical"
size :root.width, root.height
Label:
text: "Hauptmenü"
size_hint: 1, .2
font_size: 32
Button:
text: "Einkaufen"
font_size: 32
background_normal: ' '
background_color: "#666e00"
on_release:
app.root.current = "third"
root.manager.transition.direction = "left"
Button:
text: "Einkaufsliste updaten"
font_size: 32
background_normal: ' '
background_color: "#660000"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
BLE:
id: BLE
orientation: "vertical"
Button:
text: "to first"
size_hint: 1, .1
font_size: 24
on_release:
app.root.current = "first"
root.manager.transition.direction = "right"
TextInput:
multiline: False
size_hint: 1, .1
SVE:
<ThirdWindow>:
name: "third"
SetBox:
orientation: "vertical"
size :root.width, root.height
id:SetBox
Box:
orientation: "horizontal"
size_hint: 1, .4
Button:
text: "to first"
size_hint: .2, 1
font_size: 24
on_release:
app.root.current = "first"
root.manager.transition.direction = "right"
Label:
text: "Markt auswählen"
size_hint: .8, 1
font_size: 32
Button:
text: "Supermarkt"
font_size: 32
background_normal: ' '
background_color: "#a1b2e3"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Supermarkt")
Button:
text: "Drogerie"
font_size: 32
background_normal: ' '
background_color: "#c7bbc9"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Drogerie")
Button:
text: "Baumarkt"
font_size: 32
background_normal: ' '
background_color: "#b4eeb4"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Baumarkt")
Button:
text: "Elektrogerätefachhandel"
font_size: 32
background_normal: ' '
background_color: "#f4c2c2"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Elektrogerätefachhandel")
<SVE@ScrollView>:
SLE:
id: Scrollwin
size_hint: 1, None
height: self.minimum_height
<SLE>:
# orientation: "rl-bt"
# spacing: "1dp", "1dp"
</code></pre>
我认为问题在于,kivy 在我更改变量之前创建了整个 GUI。
有没有办法重新加载屏幕,或者我是否必须为每个 market/shop 制作另一个屏幕?
可以随心所欲。您必须将项目添加到相应的布局中。我将以我前段时间做的一个项目为例:
class ExmapleApp(App):
def build(self):
#Create GridLayout where you will add and remove widgets
self.gridRooms = gridRooms = GridLayout(cols=10, padding=10, spacing=10,
row_force_default=True, row_default_height=50, size_hint_y=None)
gridRooms.bind(minimum_height=gridRooms.setter('height'))
# Generate 10 Rooms items
for i in range(10):
labl = NewLabel() #Instace of NewLabel
labl.num = str(i+1) #Number of room
labl.roomName = "Room "+str(labl.num) # Room name
labl.filename = '12916_sweet_trip_mm_kwik_mod_01.wav'
roomsList.append(labl) #This add the room to a list for further reference
gridRooms.add_widget(labl) #This add the rooms to a grid
这是目前为止的效果图:
最后,您可以向该 GridLayout 添加小部件:
#Create the object you want to Add
labl = NewLabel() #Instace of NewLabel
labl.num = str(11) #Number of room
labl.roomName = "Room "+str(labl.num) # Room name
labl.filename = '12916_sweet_trip_mm_kwik_mod_01.wav'
roomsList.append(labl) #This add the room to a list for further reference
#This add the widgets 3 secs after the program starts
Clock.schedule_once(lambda x: gridRooms.add_widget(roomsList[10]), 3) #Add room 11
您甚至可以在每次按下按钮时创建一个新的小部件。
要删除小部件,只需:
gridRooms.remove_widget(roomsList[10]) #Removes Room 11
我对 Kivy-Libaray 有疑问。我目前正在为 ShoppinglistApp 编写前端。我有一个主菜单,在那里你可以 select 你想做什么(添加列表/商店)从那里你可以到达商店 selection.
- 在商店 selection 菜单中有 4 家商店。
- 所有项目(产品)都存储在列表中。
- 如果您 select 商店,则应为(来自该商店的)每个商品创建一个按钮。
我厌倦了这个解决方案:
from kivy.app import App
from kivy.metrics import dp
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.stacklayout import StackLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
# the rest
class Produkt:
def __init__(self, name, amount, market):
self.name = name
self.amount = amount
self.market = market
eklist = []
for i in range(0, 100):
nn = "Banane" + str(i)
eklist.append(Produkt(nn, 0, "Baumarkt"))
# Define Screens
class FirstWindow(Screen):
pass
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
"""Anfang der Chose"""
class Box(BoxLayout):
pass
# Gvar is a class I created for the purpose of transporting variable(s). Especially the selected shop.
class Gvar:
def __init__(self, var1):
self.var1 = var1
def get(self):
return self.var1
gvar = Gvar("default")
# SetBox ist the Class for changing the variable through the shop selection menu.
class SetBox(BoxLayout):
def set(self, market):
gvar.var1 = market
print("Set")
print(gvar.var1)
class BLE(BoxLayout):
pass
# This is the Menus which makes Problems.
class SLE(StackLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for p in eklist:
# In theory, this if request should always be triggerd. In praxis, I made the else Request to debug.
# for Text normally would appear p.name, but I changed it for debugging. Text shown(gvar.var1) is "default".
if p.market == str(gvar.get()):
b = Button(text=str(gvar.get()), size_hint=(None, None), color="blue", size=(dp(200), dp(100)),
on_press=lambda *args: self.test1(*args, str(p.name)))
b.prod = p
self.add_widget(b)
else:
b = Button(text=str(gvar.get()), size_hint=(None, None), color="green", size=(dp(200), dp(100)),
on_press=lambda *args: self.test1(*args, str(p.name)))
b.prod = p
self.add_widget(b)
market = None
# test 1 is a placeholder for a Backend funktion
# Here I print the Produkt and gvar.var1, to debug. Here it get for gvar.var1 the in the GUI selected Value.
def test1(self, b, i):
print("Initialize test2, please wait...")
print(b.prod.name, b.prod.amount, b.prod.market, gvar.var1)
"""Ende der Chose"""
kv = Builder.load_file('einkaufsliste.kv')
class EinkaufsApp(App):
def build(self):
return kv
if __name__ == '__main__':
EinkaufsApp().run()
+
这是 Kivy 文件。
WindowManager:
FirstWindow:
SecondWindow:
ThirdWindow:</p>
<FirstWindow>:
name: "first"
Box:
orientation: "vertical"
size :root.width, root.height
Label:
text: "Hauptmenü"
size_hint: 1, .2
font_size: 32
Button:
text: "Einkaufen"
font_size: 32
background_normal: ' '
background_color: "#666e00"
on_release:
app.root.current = "third"
root.manager.transition.direction = "left"
Button:
text: "Einkaufsliste updaten"
font_size: 32
background_normal: ' '
background_color: "#660000"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
BLE:
id: BLE
orientation: "vertical"
Button:
text: "to first"
size_hint: 1, .1
font_size: 24
on_release:
app.root.current = "first"
root.manager.transition.direction = "right"
TextInput:
multiline: False
size_hint: 1, .1
SVE:
<ThirdWindow>:
name: "third"
SetBox:
orientation: "vertical"
size :root.width, root.height
id:SetBox
Box:
orientation: "horizontal"
size_hint: 1, .4
Button:
text: "to first"
size_hint: .2, 1
font_size: 24
on_release:
app.root.current = "first"
root.manager.transition.direction = "right"
Label:
text: "Markt auswählen"
size_hint: .8, 1
font_size: 32
Button:
text: "Supermarkt"
font_size: 32
background_normal: ' '
background_color: "#a1b2e3"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Supermarkt")
Button:
text: "Drogerie"
font_size: 32
background_normal: ' '
background_color: "#c7bbc9"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Drogerie")
Button:
text: "Baumarkt"
font_size: 32
background_normal: ' '
background_color: "#b4eeb4"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Baumarkt")
Button:
text: "Elektrogerätefachhandel"
font_size: 32
background_normal: ' '
background_color: "#f4c2c2"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
on_press: SetBox.set("Elektrogerätefachhandel")
<SVE@ScrollView>:
SLE:
id: Scrollwin
size_hint: 1, None
height: self.minimum_height
<SLE>:
# orientation: "rl-bt"
# spacing: "1dp", "1dp"
</code></pre>
我认为问题在于,kivy 在我更改变量之前创建了整个 GUI。 有没有办法重新加载屏幕,或者我是否必须为每个 market/shop 制作另一个屏幕?
可以随心所欲。您必须将项目添加到相应的布局中。我将以我前段时间做的一个项目为例:
class ExmapleApp(App):
def build(self):
#Create GridLayout where you will add and remove widgets
self.gridRooms = gridRooms = GridLayout(cols=10, padding=10, spacing=10,
row_force_default=True, row_default_height=50, size_hint_y=None)
gridRooms.bind(minimum_height=gridRooms.setter('height'))
# Generate 10 Rooms items
for i in range(10):
labl = NewLabel() #Instace of NewLabel
labl.num = str(i+1) #Number of room
labl.roomName = "Room "+str(labl.num) # Room name
labl.filename = '12916_sweet_trip_mm_kwik_mod_01.wav'
roomsList.append(labl) #This add the room to a list for further reference
gridRooms.add_widget(labl) #This add the rooms to a grid
这是目前为止的效果图:
最后,您可以向该 GridLayout 添加小部件:
#Create the object you want to Add
labl = NewLabel() #Instace of NewLabel
labl.num = str(11) #Number of room
labl.roomName = "Room "+str(labl.num) # Room name
labl.filename = '12916_sweet_trip_mm_kwik_mod_01.wav'
roomsList.append(labl) #This add the room to a list for further reference
#This add the widgets 3 secs after the program starts
Clock.schedule_once(lambda x: gridRooms.add_widget(roomsList[10]), 3) #Add room 11
您甚至可以在每次按下按钮时创建一个新的小部件。 要删除小部件,只需:
gridRooms.remove_widget(roomsList[10]) #Removes Room 11