Skip to content
Advertisement

Kivy Label is not showing up

So I am a beginner in kivy. I have written a programm that reads sentences from a list and displays them in a Boxlayout as buttons. The Boxlayout is in a Floatlayout, so I can control where the sentences are located. If I click one of the sentences, it splits into buttons for each word. So far so good. Now I want to create a Label, that shows up somewhere below the Boxlayout. It should show up whenever a word button is clicked, and display the same text as the button. So lets say I have this sentence as a Button:

| Hello World, this is an example sentence. |

If I click the sentence:

| Hello || World || this || is || an || example || sentence |

The words should split into indivudal buttons. When I click for example the ‘sentence’ Button, a Label should show up somewhere below having the text ‘sentence’

.py:

import kivy

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Widget, Label
from kivy.config import Config

sentences = ['This is example sentence 1.', 'This is example sentence 2.', 'This is example sentence 3.', 'This is example sentence 4.', 'This is example sentence 5.', 'This is example sentence 6.']

words = [ ['This', 'is' , 'example' ,  'sentence' , '1' ], ['This', 'is' , 'example' ,  'sentence' , '2' ], ['This', 'is' , 'example' ,  'sentence' , '3' ], ['This', 'is' , 'example' ,  'sentence' , '4' ], ['This', 'is' , 'example' ,  'sentence' , '5' ], ['This', 'is' , 'example' ,  'sentence' , '6' ] ]



class AdaptiveButton(Button):
    """This button takes as much space as it needs to contain its text."""

    def __init__(self, **kwargs):
        super(AdaptiveButton, self).__init__(**kwargs)
        self.size_hint = (None, None)
        self.bind(texture_size = self.setter("size"))


class Boxlayout(BoxLayout):
    """This will arrange all the necessary widgets."""



    def __init__(self, **kwargs):
        super(Boxlayout, self).__init__(**kwargs)
        self.orientation = "vertical"
        self.spacing = "10dp"

        for i, line in enumerate(sentences):
            abtn = AdaptiveButton(text = line, font_size=30) 
            abtn.bind(on_press = lambda btn, j = i : self.destroy_then_create(btn, j))
            self.add_widget(abtn)
    def destroy_then_create(self, btn, index):
        self.remove_widget(btn)

        box = BoxLayout(size_hint = (None, None), spacing = "10dp")

        box.bind(minimum_size = box.setter("size"))
        sentence = words[index]
        i = len(sentences)-index-1
        for word in sentence:
            abtn = AdaptiveButton(text = word)
            abtn.bind(on_press=lambda btn, j=i: show(word)) # Here is the function for #the label being binded
            box.add_widget(abtn)

        self.add_widget(box, i)

class Meaningclass(Label): # Label class
    pass


def show(k): #function for the Label

    MeC = Meaningclass()
    Meaning = Label(text=k, font_size=30)
    MeC.add_widget(Meaning)






class MyApp(App):

    def build(self):
        self.icon = 'budspencer.png'
        # creating Floatlayout
        Fl = FloatLayout()

        Box = Boxlayout(pos_hint={'x': .23, 'y': .58}) 
        
        meaning = Meaningclass(pos_hint={'x': .9, 'y': .1}) 
        Fl.add_widget(Box)
        Fl.add_widget(meaning) #Here we add the Label to the FloatLayout


        # return the layout
        return Fl


# run the App
if __name__ == "__main__":
    MyApp().run()

Advertisement

Answer

The problem is that you are actually adding a label into another label in your function show but you never accessed the label you’ve already added to the app’s subclass.

The fixes are as follows,

  1. First create a reference for that label,
    def build(self):
        ...

        Box = Boxlayout(pos_hint={'x': .23, 'y': .58}) 
        # Create a reference of the label with 'self'.
        self.meaning = Meaningclass(pos_hint={'x': .2, 'y': .1}, font_size=30) # Reduce it so that it doesn't go out of the screen.
        Fl.add_widget(Box)
        Fl.add_widget(self.meaning) #Here we add the Label to the FloatLayout
  1. Pass exactly the ‘word’ in method destroy_then_create as before using kwarg.,
        ...
        for word in sentence:
            abtn = AdaptiveButton(text = word)
            abtn.bind(on_press=lambda btn, w=word: show(w)) # Pass the word only as before using kwarg.
            box.add_widget(abtn)
        ...
  1. Now make the following changes in function show,
def show(k): #function for the Label
    # Grab the running app instance.
    app = App.get_running_app()
    # Access the label you already added to the app's subclass and set the text.
    app.meaning.text = k

You could’ve added this function show anywhere in your code but remember to access the app instance in whatever way is suitable.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement