简体   繁体   中英

Python (Kivy) - How to dynamically add buttons and bind with different arguments

I already found out how to dynamically add buttons in kivy and also how I can bind them to a method with extra arguments.

I'm gonna try to describe my problem as good as possible with a Car example: I'm kinda using MVC. The user should be able to see a list of cars and he is also able to edit, add and delete (so basic CRUD). The Car Model has properties like id, car_name, and description

The controller does CRUD operations. When it writes it will store the data in a.json file and when it reads it will store all the data in variables. I don't have any problems with the Controller or Model, this works fine.

Now I want to display all cars the user created in my View (Kivy). I decided that all cars will be displayed as a button with the car name in a MainWindow. When I click on the button it should show a new screen with the information about the car. But I don't know how I can pass the id of the car from the button which is clicked... So thats my code so far (not working):

class MainWindow(GridLayout):
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        self.cols = 1
        for car in car_cache.car_list:
            btn_car = Button(text=car.car_name, font_size=40)
            btn_car.bind(on_press=lambda x: self.select_car(btn_car, car.id))
            self.add_widget(btn_car)

    def select_car(self, instance, id):
        print(f'Car {id} selected')

The buttons are displayed correctly. The problem is, it always prints the last id from the car added to the widget no matter what button I click.

Thanks for helping.

The two comments under my question solved my problem. For the first comment:

class MainWindow(GridLayout):
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        self.cols = 1
        for car in car_cache.car_list:
            self.btn_car = Button(text=car.car_name, font_size=40)
            self.btn_car.bind(on_press=partial(self.select_car, car.id))
            self.add_widget(btn_car)

    def select_car(self, id, instance):
        print(f'Car {id} selected')

partial needs to be imported from functools. note that the parameters id and instance in the function 'select_car' changed place.

For the second comment:

class MainWindow(GridLayout):
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        self.cols = 1
        for car in car_cache.car_list:
            self.btn_car = Button(text=car.car_name, font_size=40)
            self.btn_car.bind(on_press=lambda x, bound_car=car: 
                                self.select_car(self.btn_car, bound_car.id))
            self.add_widget(btn_car)

    def select_car(self, instance, id):
        print(f'Car {id} selected')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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