Home > Enterprise >  How to create an buttonloop with parameter in kivy, after the GUI has generated?
How to create an buttonloop with parameter in kivy, after the GUI has generated?

Time:01-13

I have an problem with the Kivy-Libaray. I' m currently writing the front end, for a ShoppinglistApp. I have an main menu, where you can select what you want to do(add List/ Shop) from where you can get to the Shop selection.

  1. In the shop selection Menu are 4 Shops.
  2. all Items(Produkt) are stored in a list.
  3. If you select the Shop, then for each Item(from this Shop) a Button should be created.

I tired this solution:

       

    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()
    

Here is the Kivy file.


WindowManager:
FirstWindow:
SecondWindow:
ThirdWindow:

&ltFirstWindow&gt: 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" &ltSecondWindow&gt: 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: &ltThirdWindow&gt: 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") &ltSVE@ScrollView&gt: SLE: id: Scrollwin size_hint: 1, None height: self.minimum_height &ltSLE&gt: # orientation: "rl-bt" # spacing: "1dp", "1dp" </code></pre>

I think the Problem is, that kivy creates the whole GUI before I can change the variable. Is there a way to reload the Screen or do I have to make for each market/shop another Screen?

CodePudding user response:

It's possible to do what you want. You have to add the items to the corresponidng layout. I'll give you an example with a project I did some time ago:

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

Here's an image of how it looks so far: enter image description here

Finally, you can add widgets to that 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

enter image description here

You can even have a callback to create a new widget everytime you press a button. To remove a widget just:

gridRooms.remove_widget(roomsList[10]) #Removes Room 11
  •  Tags:  
  • Related