Search code examples
pythonkivykivy-language

How to write into kivy's Label from a file Dynamically?


I am new to Python UI programming. I want to build a GUI in which when you enter a letter and you will get the code to print that letter using a star pattern or any other character pattern. I stored the codes of pattern codes of all letters in a separate text file like a.txt,b.txt etc.. I also wrote code for some special characters like a love symbol or a cake. But for now, I am working on displaying the pattern code for letters. I have to read input from the user say 'm' and I read the text from the m.txt file. All I have to do now is to display these contents on GUI using the Label tag. My code doesn't print anything on the screen.

Please Can someone make time for me and look into my code. Thanks in advance

Here's my Python File

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup


def show_popup():
    show = P()
    popupWindow = Popup(title = "Error",content = show,size_hint = (None,None),size =(400,400))
    popupWindow.open()




class P(FloatLayout):
    pass

class Code(Screen):
    def display(self,char):
        try:
            with open("{}.txt".format(char),"r") as f:
                contents = f.read()
                # I am sure that the contents are read properly
                # bcoz I printed them on IDLE and it worked
            main_label = Label()
            main_label.txt = contents
        except:
            show_popup()#if it is an invalid letter like(@,*,&)

class SecondPage(Screen):
    #SecondPage asks the user to enter a letter
    letter = ObjectProperty(None)
    def Enter(self):
        #this method checks whether the user entered a valid letter or not
        if len(self.letter.text)==1:
            char = self.letter.text
            char = char.lower()
            c = Code()
            c.display(char)#passing this character display method
            
        else:
            show_popup()

            

class MainPage(Screen):
    #Main Page has two buttons asking the user whether
    #he want code for special character or a letter
    pass


class WindowManager(ScreenManager):
    pass




class Sowmya(App):
    def build(self):
        return WindowManager()
if __name__ == "__main__":
    Sowmya().run()

And here's my .kv file

<P>:
    Label:
        text:"Please enter a valid letter"
        size_hint:0.6,0.2
        pos_hint:{"x":0.2,"top":1}

<WindowManager>:
    MainPage:
    SecondPage:
    Code:

<MainPage>:
    name:"main"

    Button:
        text: 'Letters'
        pos_hint : {'x':.4,'y':.2,'left':.3}
        on_release:
            app.root.current = "second"
            root.manager.transition.direction = "left"
        font_size: 20 
        background_color: (1, 1, 1, 1) 
        color: (1, 1, 1, 1)
        size_hint:.4,.3
    Button:
        text: 'Special'
        pos_hint : {'x':.4,'y':.5,'left':.3}
        font_size: 20 
        background_color: (1, 1, 1, 1) 
        color: (1, 1, 1, 1)
        size_hint:.4,.3


<SecondPage>:
    letter:letter
    name:"second"
    GridLayout:
        cols:1
        GridLayout:
            cols:2
            Label:
                text:"Enter Letter:"
            TextInput:
                id:letter
                multiline:False
        Button:
            text : "Enter"
            on_release:
                root.Enter()
                app.root.current = "code"
                
        Button:
            text:"Go Back"
            on_release:
                app.root.current = "main"
                root.manager.transition.direction = "right"


<Code>:
    name:"code"
    Label:
        size_hint:0.6,0.2
        pos_hint:{"x":0.2,"top":1}    

    



Solution

  • Two similar problems in your code:

    First, in your Code class, the line:

            main_label = Label()
    

    creates a new Label, which is not in your GUI, so setting the text of that new Label will not have any effect on your GUI. So, you can correct this by accessing the actual Label that is in your Code Screen:

    class Code(Screen):
        def display(self, char):
            try:
                with open("{}.txt".format(char), "r") as f:
                    contents = f.read()
    
                # don't create a new Label, use the one in this Screen
                self.ids.main_label.text = contents
    
                # switch to this Screen
                self.manager.current = 'code'
            except:
                show_popup()  # if it is an invalid letter like(@,*,&)
    

    For this to work, you need to add the id main_label in the kv:

    <Code>:
        name:"code"
        Label:
            id: main_label  # id for accessing this Label
            size_hint:0.6,0.2
            pos_hint:{"x":0.2,"top":1}   
    

    A similar error in your SecondPage class where you are creating a new instance of Code rather than accessing the one that is already part of your GUI. This can be corrected by using the ScreenManager to access the Code Screen:

    class SecondPage(Screen):
        # SecondPage asks the user to enter a letter
        letter = ObjectProperty(None)
    
        def Enter(self):
            # this method checks whether the user entered a valid letter or not
            if len(self.letter.text) == 1:
                char = self.letter.text
                char = char.lower()
                # c = Code()
                c = self.manager.get_screen('code')  # get Code Screen that was created by the `kv`
                c.display(char)  # passing this character display method
    
            else:
                show_popup()
    

    Note that whenever you use a class name followed by () you are creating a new instance of that class that likely has no relation to any instance of that class that is already in your App.