Search code examples
pythonpython-3.xpython-2.7kivykivy-language

Kivy - Adding Buttons To Screen Through Python


I am trying to make a screen view with buttons. The problem is that the amount of buttons needed each time will change, therefore I am not able to use the kv file to make theses buttons. I am having trouble adding buttons through the normal python code. Any help is appreciated.

import kivy
import webbrowser
import MSQLHandler
kivy.require('1.10.0')


from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.listview import ListItemButton
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition, CardTransition,  SwapTransition, FadeTransition, WipeTransition, FallOutTransition, RiseInTransition, NoTransition
from kivy.lang import Builder
from kivy.uix.button import Button

class Login_Failed(Screen):

    def changeScreen(self, next_screen):
        self.manager.current = next_screen



class Loged_In(Screen):

    def changeScreen(self, next_screen):
        self.manager.current = next_screen


class Registers(Screen):

    def changeScreen(self, next_screen):
        self.manager.current = next_screen


class Login_Screen(Screen):

    teacher_connect_image = ObjectProperty()

    username_text_input = ObjectProperty()
    password_text_input = ObjectProperty()
    teacherid_text_input = ObjectProperty()

    def LoginButton(self):

        if self.teacherid_text_input.text == "":
            Number = 0
        else:
            Number = int(self.teacherid_text_input.text)

        MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number)

        def changeScreen(self, next_screen):
            self.manager.current = next_screen

        if MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is True:
            print("Returns True")
            changeScreen(self, "Loged_In")
        elif MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is False:
            print("Returns False")
            changeScreen(self, "Login_Failed")
        else:
            print("Null")




class ScreenManagerr(ScreenManager):
    pass


class MainKivyFrameApp(App):

    def build(self):

        Registers().add_widget(Button(text="Helpp"))

        return ScreenManagerr()

mainFrame = MainKivyFrameApp()
mainFrame.run()

If you look to where the app is being built, you will see: Registers().add_widget(Button(text="Helpp"))

This is where I have tried to add a Button to the screen of Registers. This doesn't give me any errors, but it still does not show the button.


Solution

  • Solution

    In the kv file, add an event (on_enter or on_pre_enter) in each screen and bind it to a callback method as shown in the following snippets and example. Remember to remove the widgets that were added dynamically before leaving the current screen, by adding an event (on_leave or on_pre_leave).

    Snippets

    <Registers>:
        on_pre_enter: self.add_buttons(n)
        on_leave: self.remove_buttons()
    

    Example

    main.py

    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.uix.button import Button
    from kivy.core.window import Window
    from kivy.properties import ObjectProperty, NumericProperty
    
    
    class MyScreenManager(ScreenManager):
        total_button = NumericProperty(2)
    
    
    class Login(Screen):
        login = ObjectProperty(None)
    
        def on_pre_enter(self):
            Window.size = (400, 300)
    
        def check_password(self, instance, password):
            if password == "pwd":
                instance.current = "registers"
    
    
    class Registers(Screen):
        container = ObjectProperty(None)
    
        def on_pre_enter(self):
            Window.size = (800, 600)
    
        def add_buttons(self, n):
            print("Registers: n={}".format(n))
            for i in range(n):
                self.container.add_widget(Button(text="Button #{}".format(i), id=str(i)))
    
        def remove_buttons(self, *args):
            for child in [child for child in self.container.children]:
                self.container.remove_widget(child)
    
    
    class Welcome(Screen):
        pass
    
    
    class TestApp(App):
        title = "ScreenManager - Add Widgets Dynamically"
    
        def build(self):
            return MyScreenManager()
    
    
    if __name__ == "__main__":
        TestApp().run()
    

    test.kv

    #:kivy 1.10.0
    #:import SwapTransition kivy.uix.screenmanager.SwapTransition
    
    <MyScreenManager>:
        transition: SwapTransition()
        Login:
        Registers:
            on_pre_enter:
                self.add_buttons(app.root.total_button)
            on_leave:
                self.remove_buttons()
        Welcome:
    
    <Login>:
        id: login
        name: "login"
        login: login
        GridLayout:
            size_hint: (0.5, 0.5)
            pos_hint: {"center_x": 0.5, "center_y": 0.6}
            rows: 3
            padding: 20
    
            Label:
                size_hint: (0.2, 0.2)
                text:"Password:"
                font_size: 30
                halign: "center"
                valign: "middle"
    
            TextInput:
                id: password
                size_hint: (0.2, 0.06)
                cursor_blink: True
                font_size: 20
                multiline: False
                password: True
    
            Button:
                text: "Continue"
                size_hint: (0.2, 0.08)
                on_release:
                    root.login.check_password(root.manager, password.text)
    
    <Registers>:
        name:'registers'
        container: container
        BoxLayout:
            orientation: 'vertical'
            Button:
                text: 'Return to Login'
                on_press: root.manager.current = 'login'
            Button:
                text: 'Next Screen'
                on_press: root.manager.current = 'welcome'
            BoxLayout:
                id: container
                orientation: 'vertical'
    
    <Welcome>:
        name:'welcome'
        BoxLayout:
            Label:
                text: 'Welcome!'
            Button:
                text: 'Return to Registers'
                on_press:
                    app.root.total_button = 5
                    root.manager.current = 'registers'
    

    Output

    Img01 - App Startup - Login Screen Img02 - Registers Screen Img03 - Welcome Screen Img04 - Registers Screen