Search code examples
pythonpython-3.xkivykivy-language

Why is kivy not processing a rule in my kv file even though the class name is listed?


I'm a kivy newbie, trying to write an app for my own personal use. I'm using ScreenManager. The rule for the class for the first screen (ThoughtsClass) is read correctly from the kv file and executed. But when it comes to the second screen (Distortion), Kivy doesn't read the rule and I get only a blank screen. If I manually call add_widget on a widget, that widget appears. But nothing is being processed from the kv file.

Here is my kv file:

Root:
    ThoughtsClass:
    Distortion:


<ThoughtsClass>:
    cols: 1
    thought: thought
    id: thoughtclass

    TextInput:
        id: thought
        multiline: False

    BoxLayout:
        size_hint_y: 0.25
        orientation: 'horizontal'

        Button:
            text: 'Next Thought'
            on_press: thoughtclass.nextthought()

        Button:
            text: 'Done'
            on_press: thoughtclass.donethought()

<Distortion>:
    cols: 1
    disttext: disttext
    thoughtdisplay: thoughtdisplay

    Label:
        id:thoughtdisplay
        text: ''

    BoxLayout:
        orientation: 'horizontal'
        SelectDist:
            id: disttext

And here is the main Python code:

#!/usr/bin/env python3

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.properties import StringProperty, ObjectProperty, DictProperty
from kivy.storage.dictstore import DictStore
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen

class Root(ScreenManager):

    def __init(self, **kwargs):
        super(Root, self).__init__(self,**kwargs)


class ThoughtsClass(Screen):
    thought = ObjectProperty()
    negstatements = DictProperty()
    distmeanings = DictProperty()

    def __init__(self, **kwargs):
       super(ThoughtsClass, self).__init__(**kwargs)
       self.distmeanings = distortions
       self.name = 'Thoughts'


    def nextthought(self):
        print ('Thought: ' + self.thought.text)
        if self.thought.text:
            self.negstatements[self.thought.text] = {'distortion':'', 'rational':''}
        self.thought.text = ''

    def donethought(self):
        print ('Done pressed')
        if self.thought.text not in self.negstatements:
            self.nextthought()
        root.current = 'Distortions'
        root.current_screen.thoughts = self.negstatements


class Distortion(Screen):
    disttext = ObjectProperty()
    thoughts = DictProperty()
    thoughtdisplay = ObjectProperty()

    def __init__(self, **kwargs):
        super(Distortion, self).__init__(**kwargs)
        self.name = 'Distortions'

    def display_thought(self):
        for thoughttext in self.thoughts:
            self.thoughtdisplay.text = thoughttext
        dist_dd = SelectDist()
        dist_dd.build_dd()
        distbutton = Button(text='Choose a distortion:')
        distbutton.bind(on_release=dist_dd.open)
        dist_dd.bind(on_select=self.choose_dist())

    def choose_dist(self, instance, value):
        print ("Chose " + value)

class SelectDist(DropDown):

    def __init__(self, **kwargs):
        super(SelectDist, self).__init__(**kwargs)

    def build_dd(self):
        for diststring in distortions:
            btn = Button(text = diststring)
            btn.bind(on_release=lambda btn: self.select(btn.text))
            self.add_widget(btn)


class ThreeColumnApp(App):

    def build(self):
        global root
        root = Root()
        root.add_widget(ThoughtsClass())
        root.add_widget(Distortion())
        return root

if __name__ == '__main__':
    distortions = {}
    cbtinstance = ThreeColumnApp()
    cbtinstance.run()

I cannot figure out why this is happening...


Solution

  • The Distortion Screen appears blank because your kv rule for that Screen does not define anything that will be apparent when it is displayed. Try changing:

    Label:
        id:thoughtdisplay
        text: ''
    

    to:

    Label:
        id:thoughtdisplay
        text: 'Nothing yet!!'
    

    and you should see that Label when the Distortion Screen is displayed.