Search code examples
pythonpython-3.xkivykivy-language

My two screens overlap but only if the popup has been activated


For my very first Kivy project I want to create a basic app that will store my passwords. If you happen to get the access code wrong, a popup will appear that says "Incorrect Password". Whenever I put the password in correctly first try the transitions work with no issues, but if the password is ever wrong and the popup appears, any subsequent attempts will result in the two pages overlapping.

main.py:

import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout

class PassWindow(Screen):
    pass

class MainWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class PassPopup(FloatLayout):
    pass

def openPopup():
    show = PassPopup()

    global popupWin
    popupWin = Popup(title="Error", content=show, size_hint=(None, None), size=(400, 400))

    popupWin.open()

def closePopup():
    popupWin.dismiss()



kv = Builder.load_file("my.kv")

class MyApp(App):
    def build(self):
        return kv

if __name__ == "__main__":
    MyApp().run()

my.kv:

#:import openPopup main.openPopup
#:import closePopup main.closePopup

WindowManager:
    PassWindow:
    MainWindow:

<Button>:
    font_size: 30
    color: 0.33, 0, 0.51, 1

<Label>:
    color: 1, 1, 1, 1

<PassWindow>:
    name: "passWin"
    id: passWin
    Label:
        text: "Password Storage"
        pos_hint: {"top": 1}
        font_size: 50
        size_hint: 1, 0.2

    Label:
        text: "Please Input Code to Access"
        pos_hint: {"top": .8}
        font_size: 50
        size_hint: 1, 0.2

    TextInput:
        id: codeInput
        multiline: False
        password: True
        font_size: 55
        size_hint: 0.6, 0.2
        pos_hint: {"x": .2, "top": .6}

    Button:
        text: "Submit"
        size_hint: 0.5, 0.2
        pos_hint: {"x": .25, "top": .35}
        
        on_release:
            app.root.current = "mainWin" if codeInput.text == "1234" else openPopup()
            app.root.transition.direction = "left"
            codeInput.text = ""

<PassPopup>:
    Label:
        text: "Incorrect Password"
        size_hint: 0.6, 0.2
        pos_hint: {"x": 0.2, "top": 0.8}
        font_size: 30

    Button:
        text: "Close"
        size_hint: 0.8, 0.2
        pos_hint: {"x": 0.1, "top": 0.3}

        on_release:
            closePopup()


<MainWindow>:
    name: "mainWin"

    Button:
        text: "Exit"
        size_hint: 1, 0.2

        on_release: 
            app.root.current = "passWin"
            root.manager.transition.direction = "right"

Solution

  • The logic in your on_release: of the Submit Button is incorrect. The line:

    app.root.current = "mainWin" if codeInput.text == "1234" else openPopup()
    

    sets the current screen to "mainWin" if the password provided is "1234", otherwise, it sets the current screen to the return value of openPopup() (which is None). I suspect that is the cause of the strange behavior. To fix that, use the following for the on_release:

        on_release:
            if codeInput.text == "1234": app.root.current = "mainWin"
            else: openPopup()
            app.root.transition.direction = "left"
            codeInput.text = ""
    

    See the documentation.