Python / Kivy:如何在循环中传递参数

时间:2018-03-16 06:37:21

标签: python kivy kivy-language

我有两个文件test.pytest.kv。当我运行test.py并点击show按钮时,标签和值显示。
当我点击任意label (Item1,Item2,Item3 )时,它只会传递13中的最后一个ID def say_hello 有人能告诉我,我在哪里犯了错误?

test.py

from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window

Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)

class MyLabel(Label):
    pass

class Invoice(Screen):
    def __init__(self, **kwargs):
        super(Invoice, self).__init__(**kwargs)

    def abc(self):
        #fetching from database
        arr = [(11, 'Item1', '1001'), (12, 'Item2', '2001'), (13, 'Item3', '102')]
        layout = self.ids['invoices']
        for row in arr:
            layout.add_widget(MyLabel(text=str('[ref=world]'+row[1])+'[/ref]',size_hint_x=.35, halign='left', markup=True,on_ref_press=lambda *args: self.say_hello(row[0]) ))
            layout.add_widget(MyLabel(text=str(row[2]),size_hint_x=.15, halign='right' ))

    def say_hello(self, id='Zero'):
        print(id)



class Test(App):

    def build(self):
        return self.root

if __name__ == '__main__':
    Test().run()

test.kv

<Button@Button>:
    font_size: 15
    font_name: 'Verdana'
    size_hint_y:None
    height: 30

<MyLabel>:
    font_size: 15
    font_name: 'Verdana'
    size_hint_y:None
    height: 30
    text_size: self.size
    valign: 'middle'
    canvas.before:
        Color:
            rgb: .6, .6, .6
        Rectangle:
            pos: self.pos
            size: self.size

Invoice:
    BoxLayout:
        orientation: "vertical"
        padding : 15, 15

        BoxLayout:
            orientation: "vertical"
            padding : 5, 5
            size_hint: .6, None
            pos_hint: {'x': .18,}


            BoxLayout:
                orientation: "horizontal"
                padding : 5, 5
                spacing: 10, 10
                size: 800, 40
                size_hint: 1, None

                Button:
                    text: "Show"
                    size_hint_x: .05
                    spacing_x: 30
                    on_press:root.abc()

        BoxLayout:
            orientation: "horizontal"
            size_hint: 1, 1

            BoxLayout:
                orientation: "vertical"
                size_hint: .5, 1
                padding : 0, 15
                spacing: 10, 10
                size: 500, 30

                GridLayout:
                    id: invoices
                    cols: 2
                    #orientation: "horizontal"
                    padding : 5, 0
                    spacing: 10, 0
                    #size: 500, 30
                    size_hint: 1, 1
                    pos: self.pos
                    size: self.size

1 个答案:

答案 0 :(得分:1)

问题是你要覆盖lambda函数的值,解决方法是将该值作为lambda函数的参数传递:

<强> python3:

layout.add_widget(MyLabel(text=str('[ref=world]'+row[1])+'[/ref]',
    size_hint_x=.35, 
    halign='left', 
    markup=True,
    on_ref_press=lambda *args, _id=row[0]: self.say_hello(_id) ))

上一个方法适用于python3,因为python2存在语法错误,所以我们将使用funcions.partial

from functools import partial

[...]

def abc(self):
    #fetching from database
    arr = [(11, 'Item1', '1001'), (12, 'Item2', '2001'), (13, 'Item3', '102')]
    layout = self.ids['invoices']
    for row in arr:
        layout.add_widget(MyLabel(text=str('[ref=world]'+row[1])+'[/ref]', 
            size_hint_x=.35, 
            halign='left', 
            markup=True,
            on_ref_press=partial(self.say_hello, row[1])))
        layout.add_widget(MyLabel(text=str(row[2]),size_hint_x=.15, halign='right' ))

def say_hello(self, id, *args):
    print(id)