Kivy、StackLayout、对象顺序
Kivy, StackLayout, object order
我有一个带有 StackLayout 的屏幕。堆栈的第一行包括一个文本输入和一个“+”按钮,这意味着在循环中的实际行下方添加另一个相同的行(即另一个带有另一个 "add" 按钮的文本输入)。然后有一个 "Save" 按钮,它应该总是在堆栈的末尾。
字典应该稍后在按下保存按钮时从文本字段中获取输入,但这应该与我的问题无关。
我的代码有两个问题:
- 首先,当我连续按下“+”按钮时,突出显示的按钮不是这个按钮本身,而是下面一行中的按钮(例如,如果有三行,我按下按钮第二行,第三行的按钮高亮显示)
- 其次,也是最重要的一点,从第二行开始,每次按下“+”按钮都会在实际行上方添加一个新行,而不是在其下方。
我知道 kivy 为小部件分配了相反的顺序(即最后添加的将首先绘制),这就是我手动为新行分配索引的原因。但是,我无法实现所需的行为。
这是一个最小的工作版本:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
class AddWindow(Screen):
def __init__(self, **kwargs):
super(AddWindow, self).__init__(**kwargs)
self.grid = StackLayout()
self.grid.pos_hint = {"x":0.05,"top":0.8}
self.grid.size_hint = (0.9,None)
self.add_widget(self.grid)
self.i = 1
self.n = 1
self.inputs = {}
self.ing1 = TextInput(size_hint=(0.9,'0.3sp'))
self.grid.add_widget(self.ing1)
self.inputs['0'] = 'ing1'
self.addIng = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addIng.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addIng)
self.doneButton = Button(text="Save")
self.grid.add_widget(self.doneButton, index=0)
def addIngredient (self, instance):
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.inputs[self.i] = 'ing{}'.format(self.i+1)
self.grid.add_widget(self.ing, index=self.n+1)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext, index=self.n+2)
self.i += 1
self.n += 2
print(self.inputs)
WMan = ScreenManager()
WMan.add_widget(AddWindow(name='add'))
class RecipApp(App):
def build(self):
return WMan
if __name__ == "__main__":
RecipApp().run()
我错过了什么?为了更清楚起见,这是一个屏幕截图:
Screenshot
这是一种蛮力方法,通过在每次按下 +
`按钮时重建 StackLayout
来执行您想要的操作:
def addIngredient(self, instance):
tmp_children_list = self.grid.children[:]
self.grid.clear_widgets()
for index in range(len(tmp_children_list)-1, -1, -1):
child = tmp_children_list[index]
self.grid.add_widget(child)
if child == instance:
# this is the pressed Button, so add new row after it
self.n += 1
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.ing.text = str(self.n) # add text just for identification
self.grid.add_widget(self.ing)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext)
这是一种快速而肮脏的方法,由于删除并添加了保存按钮,您的问题应该得到解决。在你最终再次添加保存按钮之前,你在这些操作之间添加了一个新行。希望它能帮助你调整你的代码。关键部分是AddButton的自定义on_press方法。
from kivy.app import App
from kivy.uix.stacklayout import StackLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.core.window import Window
class AddButton(Button):
def __init__(self, **kwargs):
super(AddButton, self).__init__(**kwargs)
def on_press(self):
self.parent.remove_widget(self.parent.save_btn)
self.parent.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - self.parent.padding[1], Window.height * 0.1)))
self.parent.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
self.parent.add_widget(self.parent.save_btn)
class MyApp(App):
def build(self):
Window.size = (400, 600)
layout = StackLayout(orientation="lr-tb", padding=(20, 40))
layout.save_btn = Button(text="Save", size_hint=(None, None),
size=(Window.width - layout.padding[1], Window.height * 0.1))
layout.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - layout.padding[1], Window.height * 0.1)))
layout.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
layout.add_widget(layout.save_btn)
return layout
MyApp().run()
我有一个带有 StackLayout 的屏幕。堆栈的第一行包括一个文本输入和一个“+”按钮,这意味着在循环中的实际行下方添加另一个相同的行(即另一个带有另一个 "add" 按钮的文本输入)。然后有一个 "Save" 按钮,它应该总是在堆栈的末尾。 字典应该稍后在按下保存按钮时从文本字段中获取输入,但这应该与我的问题无关。
我的代码有两个问题:
- 首先,当我连续按下“+”按钮时,突出显示的按钮不是这个按钮本身,而是下面一行中的按钮(例如,如果有三行,我按下按钮第二行,第三行的按钮高亮显示)
- 其次,也是最重要的一点,从第二行开始,每次按下“+”按钮都会在实际行上方添加一个新行,而不是在其下方。
我知道 kivy 为小部件分配了相反的顺序(即最后添加的将首先绘制),这就是我手动为新行分配索引的原因。但是,我无法实现所需的行为。
这是一个最小的工作版本:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
class AddWindow(Screen):
def __init__(self, **kwargs):
super(AddWindow, self).__init__(**kwargs)
self.grid = StackLayout()
self.grid.pos_hint = {"x":0.05,"top":0.8}
self.grid.size_hint = (0.9,None)
self.add_widget(self.grid)
self.i = 1
self.n = 1
self.inputs = {}
self.ing1 = TextInput(size_hint=(0.9,'0.3sp'))
self.grid.add_widget(self.ing1)
self.inputs['0'] = 'ing1'
self.addIng = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addIng.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addIng)
self.doneButton = Button(text="Save")
self.grid.add_widget(self.doneButton, index=0)
def addIngredient (self, instance):
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.inputs[self.i] = 'ing{}'.format(self.i+1)
self.grid.add_widget(self.ing, index=self.n+1)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext, index=self.n+2)
self.i += 1
self.n += 2
print(self.inputs)
WMan = ScreenManager()
WMan.add_widget(AddWindow(name='add'))
class RecipApp(App):
def build(self):
return WMan
if __name__ == "__main__":
RecipApp().run()
我错过了什么?为了更清楚起见,这是一个屏幕截图: Screenshot
这是一种蛮力方法,通过在每次按下 +
`按钮时重建 StackLayout
来执行您想要的操作:
def addIngredient(self, instance):
tmp_children_list = self.grid.children[:]
self.grid.clear_widgets()
for index in range(len(tmp_children_list)-1, -1, -1):
child = tmp_children_list[index]
self.grid.add_widget(child)
if child == instance:
# this is the pressed Button, so add new row after it
self.n += 1
self.ing = TextInput(size_hint=(0.9,'0.3sp'))
self.ing.text = str(self.n) # add text just for identification
self.grid.add_widget(self.ing)
self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
self.addNext.bind(on_press=self.addIngredient)
self.grid.add_widget(self.addNext)
这是一种快速而肮脏的方法,由于删除并添加了保存按钮,您的问题应该得到解决。在你最终再次添加保存按钮之前,你在这些操作之间添加了一个新行。希望它能帮助你调整你的代码。关键部分是AddButton的自定义on_press方法。
from kivy.app import App
from kivy.uix.stacklayout import StackLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.core.window import Window
class AddButton(Button):
def __init__(self, **kwargs):
super(AddButton, self).__init__(**kwargs)
def on_press(self):
self.parent.remove_widget(self.parent.save_btn)
self.parent.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - self.parent.padding[1], Window.height * 0.1)))
self.parent.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
self.parent.add_widget(self.parent.save_btn)
class MyApp(App):
def build(self):
Window.size = (400, 600)
layout = StackLayout(orientation="lr-tb", padding=(20, 40))
layout.save_btn = Button(text="Save", size_hint=(None, None),
size=(Window.width - layout.padding[1], Window.height * 0.1))
layout.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - layout.padding[1], Window.height * 0.1)))
layout.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
layout.add_widget(layout.save_btn)
return layout
MyApp().run()