ThomasATU
ThomasATU

Reputation: 582

how to use the .kv file and .py properly? - calling functions from .kv how to structure .py

Trying to understand kivy.

Working on a simple application that involves a few screens. Currently, I am trying to call a pop up window from a button on_release in the ... without success. Error:

 Traceback (most recent call last):
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 725, in _apply_rule
     raise AttributeError(key)
 AttributeError: release
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:/Users/thoma/PycharmProjects/FacesGUI/main.py", line 36, in <module>
     kv = Builder.load_file("my.kv")
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 301, in load_file
     return self.load_string(data, **kwargs)
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 405, in load_string
     rule_children=rule_children)
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 657, in _apply_rule
     root=rctx['ids']['root'], rule_children=rule_children)
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\uix\widget.py", line 469, in apply_class_lang_rules
     rule_children=rule_children)
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 538, in apply
     rule_children=rule_children)
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 734, in _apply_rule
     '{}: {}'.format(e.__class__.__name__, e), cause=tb)
 kivy.lang.builder.BuilderException: Parser: File "C:\Users\thoma\PycharmProjects\FacesGUI\my.kv", line 100:
 ...
      98:                    center_x: self.parent.center_x
      99:                    center_y: self.parent.center_y
 >>  100:                    on_release: root.show_popup()
     101:
     102:
 ...
 AttributeError: release
   File "C:\Users\thoma\PycharmProjects\FacesApp\venv\lib\site-packages\kivy\lang\builder.py", line 725, in _apply_rule
     raise AttributeError(key)

I have tried calling using root, app, self and creating an instance of MyMainApp() and passing that in. ????????

I noticed that some users recommend using builder strings in the .py whilst others suggest using the .kv file for layout etcs..

What are the advantages or disadvantages to one or the other..?? Whilst I am used to xml layouts and java/kotlin classes for the logic, using .kv has been a bit... confusing.

my.kv

<P>:
    Label:
        text: "Eneter Name or Type 'skip':"

    TextInput:
        text: ""

    Button:
        text: "Submit"




WindowManager:
    MainWindow:
    SecondWindow:

<MainWindow>:
    name: "main"

    GridLayout:
        cols:2


        Button:
            text:"Live Camera"
            on_press: root.activatecamera()

        Button:
            text:"SD Card"
            on_press: root.sdcard()

        Button:
            text:"Event Images"
            on_press: root.viewEventImages()

        Button:
            text:"Event Faces"
            on_release:
                app.root.current = "eventfaces"
                root.manager.transition.direction = "left"

        Button:
            text:"List Names"
            on_press: root.listknownfaces()

        Button:
            text:"View Log"
            on_press: root.pipeout()

        Button:
            text:"Scan Directory"
            on_press: root.scanDirectory()

        Button:
            text:"Facial Recognition on Image"
            on_press: root.metadataRead()


        Button:
            text:"Label Image"
            on_press: root.metadataRead()



        Button:
            text:"Blur Faces"
            on_press: root.metadataRead()

        Button:
            text: "Metadata"
            on_release:
                app.root.current = "second" if passw.text == "tim" else "main"
                root.manager.transition.direction = "left"

        Button:
            text: "Misc."
            on_release:
                app.root.current = "second" if passw.text == "tim" else "main"
                root.manager.transition.direction = "left"


<SecondWindow>:
    name: "eventfaces"


    GridLayout:
        cols:1
        rows:2

        GridLayout:
            cols:4

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed1.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y
                    on_release: root.show_popup()


            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed2.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y


            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed3.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed4.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y


            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed5.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed6.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y


            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed7.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed8.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed9.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed10.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y

            Button:
                id: myButton
                Image:
                    source: "unnamed/unnamed11.jpg"
                    center_x: self.parent.center_x
                    center_y: self.parent.center_y



            Button:
                text: "Main Menu"
                on_release:
                    app.root.current = "main"
                    root.manager.transition.direction = "left"

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup


class P(BoxLayout):
    pass


class MainWindow(Screen):
    pass


class SecondWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass


def show_popup():
    show = P()  # Create a new instance of the P class

    popupWindow = Popup(title="Enter Name or Type 'skip': ", content=show, size_hint=(None, None), size=(400, 400))
    # Create the popup window

    popupWindow.open()  # show the popup


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


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


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

If someone can guide me as to whether I should go with the Builder strings process or .kv and/or how I might create a pop up with a label, textinput and button and call from button in it would be much appreciated.

I believe there is an error with my .py file regarding structure. I have tried moving the def show_popup() into the SecondWindow class as I saw in an example, without success.

Do the def(s) need to be assigned to each window? or can they be called from outside the window class?

Thanks in advance. I know its a long post for a simple task. :/

Upvotes: 0

Views: 1019

Answers (1)

John Anderson
John Anderson

Reputation: 38822

The on_release: parameter is not supported for an Image. You need to move it to the Button:

        Button:
            id: myButton
            on_release: root.show_popup()
            Image:
                source: "unnamed/unnamed1.jpg"
                center_x: self.parent.center_x
                center_y: self.parent.center_y

Also, note that an id can only reference one Widget, so the myButton id will only reference the last Button with that id.

Upvotes: 2

Related Questions