KVLang Series – 8 – Inter-Widget Communication (IWC)

KVLang Series – 8

← Previous                     

Inter-Widget Communication (IWC) with Dynamic Classes

Content:
– .kv file
– .py file
– Screenshot of output

Make topic comments here.
See:
Dynamic Classes
Referencing Widgets
Accessing Widgets

.kv file

Here is the kvlang file. It contains 3 Dynamic classes, all derived from BoxLayout.

  • <LblTxtBtn>
  • <LblTxt>
  • <MyLayout>

The MyLayout Class instantiates
– 2 <LblTxt> classes and
– 2 <LblTxtBtn> classes

The MyLayout Class is instantiated as the Root Rule on the last line.

Pressing the ‘myTxtVal to …’ button in a LblTxtBtn class, copies the value of that LblTxtBtn’s TextInput widget into the “corresponding” LblTxt’s TextInput widget.

# iwc.kv
# see https://groups.google.com/d/topic/kivy-users/FdOhizCm7Ns/discussion
# KV Lang http://kivy.org/docs/guide/lang.html#
# Accessing Widgets defined in Python http://kivy.org/docs/guide/lang.html#accessing-widgets-defined-inside-kv-lang-in-your-python-code
# Dynamic Classes - http://kivy.org/docs/api-kivy.lang.html
# Referencing Widgets http://kivy.org/docs/guide/lang.html#referencing-widgets


<LblTxtBtn@BoxLayout>:
    l_text: '0default'
    t_text: '1default'
    b_text: '2default'

    o_text: 'default'
    the_btn: btn

    orientation: 'horizontal'
    Label:
        text: root.l_text
    TextInput:
        id: txt
        multiline: False
        text: root.t_text
    Button:
        id: btn
        text: root.b_text 
        on_release: root.o_text = txt.text

<LblTxt@BoxLayout>:
    l_text: '0default'
    t_text: '1default'
    orientation: 'horizontal'
    Label:
        text: root.l_text
    TextInput:
        multiline: False
        text: root.t_text


<MyLayout@BoxLayout>:  
    orientation: 'vertical'
    str_prop0: ltb0.o_text
    str_prop1: ltb1.o_text

    LblTxt:   
        id: lt0
        l_text: 'LblTxtInput0:'
        t_text: root.str_prop0

    LblTxt: 
        id: lt1
        l_text: 'LblTxtInput1:'
        t_text: root.str_prop1

    LblTxtBtn:  
        id: ltb0
        l_text: 'DynClassInput0:'
        t_text: 'ltb0Text0'
        b_text: 'myTxtVal to lt0'


    LblTxtBtn:   
        id: ltb1
        l_text: 'DynClassInput1:'
        t_text: 'ltb1Text1'
        b_text: 'myTxtVal to lt1'


MyLayout 

.py file

Here is the very simple Python file. All the work is done in the .kv file.

''' iwc.py
'''
import kivy
kivy.require('1.8.0')

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (430,133)

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('iwc.kv')
        return self.root

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

Screenshot of output

Here is what this looks like run on Windows XP. The operator has just pressed the ‘myTxtVal to lt0’ button.

Alt interWidgetComm.png

Advertisements

KVLang Series – 7 – Dynamic Classes

KVLang Series – 7

← Previous                      Next →

Dynamic Classes

Content:
– .kv file
– .py file
– screenshot of output

0007_dynamicClasses01.kv

Dynamic Classes, as opposed to Class Rules, allow you to inherit from a Base Class and allow you to change default values and to create bindings for all its instances, without adding any new Python code.
Dynamic Classes also replace the deprecated Templates concept.
See:
Dynamic Classes
Re-using styles in multiple widgets
Designing with the Kivy Language
Kivy Language

Here is the kvlang file.

0007_dynamicClasses01.kv

# see https://groups.google.com/d/topic/kivy-users/FdOhizCm7Ns/discussion
# KV Lang http://kivy.org/docs/guide/lang.html#
# Accessing Widgets defined in Python http://kivy.org/docs/guide/lang.html#accessing-widgets-defined-inside-kv-lang-in-your-python-code
# Dynamic Classes - http://kivy.org/docs/api-kivy.lang.html
# Referencing Widgets http://kivy.org/docs/guide/lang.html#referencing-widgets

<LblTxtBtn@BoxLayout>:
    l_text: '0default'
    t_text: '1default'
    b_text: '2default'
    orientation: 'horizontal'
    Label:
        text: root.l_text
    TextInput:
        text: root.t_text
    Button:
        text: root.b_text

<MyLayout@BoxLayout>:  
    orientation: 'vertical'

    LblTxtBtn:   
        l_text: 'DynClassInput1:'
        t_text: 'DynClassDefault Text1'
        b_text: 'DynClassPressMe 1'


    LblTxtBtn:   
        l_text: 'DynClassInput2:'
        t_text: 'DynClassDefault Text2'
        b_text: 'DynClassPressMe 2'

    LblTxtBtn:   
        l_text: 'DynClassInput3:'
        t_text: 'DynClassDefault Text3'
        b_text: 'DynClassPressMe 3'

MyLayout

0007_dynamicClasses01.py

Because the .kv file uses Dynamic Classes as opposed to Class Rules, the Python File now reverts to its former simpler self.

I.E. In the Python file, it is NOT NECESSARY to define:

from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty   

class LblTxtBtn(BoxLayout):

    l_text = StringProperty('')
    t_text = StringProperty('')
    b_text = StringProperty('')

class MyLayout(BoxLayout): pass

since it LblTxtBtn & MyLayout are Dynamic Classes in the .kv file.

Just revert to the SIMPLE 0005_nestedLayouts.py, update Window width to 430 & update the .kv filename.

''' 0007_dynamicClasses01.py
**SIMPLE** Python to display Dynamic Classes
Revert to 0005_nestedLayouts.py & update Window width & .kv filename.
'''



import kivy
kivy.require('1.8.0')

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (430,90)

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0007_dynamicClasses01.kv')
        return self.root

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

0007_dynamicClasses01 ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:

Alt 0007_dynamicClasses01.png

KVLang Series – 6 – Class Rules

KVLang Series – 6

← Previous              Next →

Class Rules

Content:
– .kv file
– .py file
– screenshot of output

0006_classRules.kv

Class Rules allow you to make your own widget from previously defined widgets.
A Class Rule defines how any instance of that widget class will appear.
See:
Rule context
Kivy Language
Referencing Widgets
Accessing Widgets defined inside Kv lang in your python code

In the following kvlang file, <LblTxtBtn> defines a Class Rule that combines [Label, Text, Button] for further instantiation.
Another unfortunate (from my perspective) requirement is that we must alter the Python file to declare l_text, t_text and b_text properties for the <LblTxtBtn> Class Rule.

<LblTxtBtn>:
    orientation: 'horizontal'

    Label:
        text: root.l_text
    TextInput:
        text: root.t_text
    Button:
        text: root.b_text


BoxLayout:
    orientation: 'vertical'    

    LblTxtBtn:
        l_text: 'init_lbl-1'
        t_text: 'init_text-1'
        b_text: 'init_btn-1'

    LblTxtBtn:
        l_text: 'init_lbl-2'
        t_text: 'init_text-2'
        b_text: 'init_btn-2'

    LblTxtBtn:
        l_text: 'init_lbl-3'
        t_text: 'init_text-3'
        b_text: 'init_btn-3'

0006_classRules.py

This is adapted from previous step. For Class Rules, as opposed to the upcoming Dynamic Classes, we need MAJOR ADDITIONS.
We need to ADD objects to allow us to use Class Rules and their properties in our .kv file.
Note how we need to look back and forth from the .kv file to the .py file to see what’s going on with the porperties.
This will NOT BE NECESSARY when we do the upcoming Dynamic Classes. Then the info will be contained in the .kv file.

ADD – imports & Class Code for LblTxtBtn classRule

from kivy.uix.boxlayout import BoxLayout    
from kivy.properties import StringProperty 
class LblTxtBtn(BoxLayout):
    l_text = StringProperty('')       
    t_text = StringProperty('')        
    b_text = StringProperty('')    
''' 0006_classRules.py
Adds class LblTxtBtn(BoxLayout), etc. to display 0006_classRules.kv
'''

import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (323,90)

from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty 

class LblTxtBtn(BoxLayout):

    l_text = StringProperty('')
    t_text = StringProperty('')
    b_text = StringProperty('')

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0006_classRules.kv')
        return self.root

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

0006_classRules ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 323
– height: 90

Alt 0006_classRules.png

KVLang Series – 5 – Nested Layouts

KVLang Series – 5

← Previous              Next →

Nested Layouts

Content:
– .kv file
– .py file
– screenshot of output

0005_nestedLayouts.kv

In this example we nest 3 horizontlly oriented BoxLayouts inside a single vertical BoxLayout which we use as the root rule.

BoxLayout:
    orientation: 'vertical'
    BoxLayout:
        orientation: 'horizontal'
        Label:
            text: 'Input1:'
        TextInput:
            text: 'Default Text1'
        Button:
            text: 'Press Me1'
    BoxLayout:
        orientation: 'horizontal'
        Label:
            text: 'Input2:'
        TextInput:
            text: 'Default Text2'
        Button:
            text: 'Press Me2'
    BoxLayout:
        orientation: 'horizontal'
        Label:
            text: 'Input3:'
        TextInput:
            text: 'Default Text3'
        Button:
            text: 'Press Me3'

0005_nestedLayouts.py

Just one minor change to update the .kv filename. By the way, if you read How to load KV, you can see an alternate way to associate the .py file with the .kv file.

''' 0005_nestedLayouts.py
Python file to display 0005_nestedLayouts.kv. 
'''

import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (331,124)


class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0005_nestedLayouts.kv')
        return self.root

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

0005_nestedLayouts ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 331
– height: 124

Alt 0005_nestedLayouts.png

KVLang Series – 4 – Vertical BoxLayout

KVLang Series – 4

← Previous              Next →

Vertical BoxLayout

Content:
– .kv file
– .py file
– screenshot of output

0004_verticalBoxLayout.kv

Just add the BoxLayout orientation: ‘vertical’ property. This arranges its contents in a vertical manner instead of the default ‘horizontal’.

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Input:'
    TextInput:
        text: 'Default Text'
    Button:
        text: 'Press Me'

0004_verticalBoxLayout.py

This is adapted from previous Python file. Again we make minor changes to update the .kv filename and give a new window height.

''' 0004_verticalBoxLayout.py
Used to display 0004_verticalBoxLayout.kv - Again, no new concepts in here.
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (323,90)

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0004_verticalBoxLayout.kv')
        return self.root

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

0004_verticalBoxLayout ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 323
– height: 124

Alt 0004_verticalBoxLayout.png

KVLang Series – 3 – More Widgets in a BoxLayout

KVLang Series – 3

← Previous              Next →

More Widgets in a BoxLayout

Content:
– .kv file
– .py file
– screenshot of output

0003_moreWidgets.kv

In the .kv file we add some more widgets under a BoxLayout.
If we added the widgets directly to the file, not being underneath our layout, it would be and ERROR because they would be considered root rules and “you can have one root rule, and any number of class or template rules.”
The BoxLayout has a default orientation: ‘horizontal’.

### 0003_moreWidgets.kv

BoxLayout:
    Label:
        text: 'Input:'
    TextInput:
        text: 'Default Text'
    Button:
        text: 'Press Me'

0003_moreWidgets.py

This is adapted from previous python file. We make minor changes to update the .kv filename and give a new window height.

''' 0003_moreWidgets.py
Used to display 0003_moreWidgets.kv - No new concepts in here.
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (323,30)

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0003_moreWidgets.kv')
        return self.root

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

0003_moreWidgets ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 331
– height: 64

Alt 0003_moreWidgets.png

KVLang Series – 2 – Window Size – Hello World Label Widget

KVLang Series – 2

← Previous              Next →

Window Size – Hello World Label Widget

Content:
– .kv file
– .py file
– screenshot of output

0002_windowSize.kv

This is the same as before. Unfortunately (from my perspective), we must alter the .py file to change the window size. If anyone knows a way to do this in a .kv file please post it to the comments. Thanks.

Label:
    text: 'A smaller hello, world.'

0002_windowSize.py

As I said earlier, Unfortunately (from my perspective), we must alter the .py file to change the window size. If anyone knows a way to do this in a .kv file please post it to the comments. Thanks.

This is adapted from 0001_helloWorld.py. To size the window:

ADD – Window Sizing Info

AFTER:  from kivy.lang import Builder    
BEFORE: class MyApp(App):   
INSERT:
from kivy.core.window import Window
Window.size = (331,234)
''' 0002_windowSize.py
Demonstrates Window Sizing - kivy.config - Config.set('graphics',
'''
import kivy
kivy.require('1.8.0') # replace with your current kivy version !

from kivy.app import App
from kivy.lang import Builder

from kivy.core.window import Window
Window.size = (331,234)

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('0002_windowSize.kv')
        return self.root

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

0002_windowSize ScreenShot

Here is what this looks like run on Windows XP. In Pixels, it has:
– width: 331
– height: 234

Alt 0002_windowSize.png