Kivy SyntaxError while overwriting instance of a class in .kv

Question:

Hi i created a class "LabelledSlider" in my .kv file that contains 2 Labels and 1 Slider with some properties already set in the definition of the class.

When i then try to change one of this properties (in this case the text of one of the Labels) it throws a SyntaxError (but the Syntax is in my opinion correct).

Here the .kv file for overview:

#:import Factory kivy.factory.Factory

<PopupStart@Popup>:
    id : popup_start
    title: "Start Function Pop-up"
    auto_dismiss: False
    size_hint : (.4, .4)

    RelativeLayout:
        size_hint : (.8, .9)
        Button:
            text: 'Close me!'
            size_hint : (.45, .25)
            pos_hint : {'center_x':0.5, 'y':0.1}
            on_release: root.dismiss()
        Label:
            text : "The start function will run the AI Algorithm n and will be provided soon"
            font_size : 15
            size_hint : (.55, .45)
            pos_hint : {'center_x':0.5, 'top':1}

<PopupCalibrate@Popup>:
    id : popup_calibrate
    title: "Calibrate Function Pop-up"
    auto_dismiss: False
    size_hint : (.4, .4)

    RelativeLayout:
        size_hint : (.8, .9)
        Button:
            text: 'Close me!'
            size_hint : (.45, .25)
            pos_hint : {'center_x':0.5, 'y':0.1}
            on_release: root.dismiss()
        Label:
            text : "The calibrate function will run the Camera Calibration n and will be provided soon"
            font_size : 13
            size_hint : (.55, .45)
            pos_hint : {'center_x':0.5, 'top':1}


<LabelledSlider>:

# The y-displacement relative to slider is +0.2 for "property" Label and -0.3 for "value" Label

    slider_value : slider.value
    property_name : property.text
    propertyX : property

    Label:
        id: property
        text: ""
        font_size : 15
        pos_hint_center_x : .5
        pos_hint_center_y : .7


    Slider:
        id : slider
        value_track : True
        value_track_color : [1, 0, 0, 1]
        range : (0, 100)                                  #Range must be checked with camera Specs!
        value : 0
        step : 1
        pos_hint_center_x : .5
        pos_hint_center_y : .5
        size_hint_y : None
        height : 50
        on_value : root.slider_value = self.value

    Label:
        text : "%(property)s at %(value)scm" % {"property" : root.property_name, "value" : str(root.slider_value)}
        font_size : 10
        pos_hint_center_x : .5
        pos_hint_center_y : .2




<CameraView>:
    playing_camera : playing_camera
    orientation : "vertical"        #should be omitted (related to BoxLayout) but still works
    Camera:
        id : playing_camera
        play : True
        index : 0

#DA ELIMINARE, MA COSI FUNZIONA
    Button:
        size_hint : (.1,.1)
        on_release : root.parent.select_camera_button()




    Label:
        text : "Camera n.%s" % str(playing_camera.index)
        font_size : "15sp"
        size_hint : (.3,.1)
        pos_hint : {'center_x':0.5, 'top':1}
        bold : True

<ControlsView>:

    focus_value : focus_slider.value

    Button:
        id : btn_start
        text : "Start"
        font_size : 20
        size_hint : (0.7,.1)
        pos_hint :  {'center_x':0.5, 'y':0.05}
        background_normal : ""
        background_color : (0,1,0,.5)
        bold : True
        on_release: Factory.PopupStart().open()
        #Check where the function definition should be placed
                                                        #Also check if "self." is the right expression

    Button:
        id : btn_calibrate
        text : "Calibrate"
        font_size : 18
        size_hint : (0.7,.1)
        pos_hint  :  {'center_x':0.5, 'top':0.75}
        background_normal : ""
        background_color : (0, 0, 1, .5)
        on_release: Factory.PopupCalibrate().open()

#Strange behaviour: If a ")" is present it will interpreted as EOF, hence returning an error

    Label:
        text : "logic.portable"
        font_size : 25
        pos_hint : {'top':1.45}

    Label:
        text : "Gewicht in g"
        pos_hint : {'center_x':0.5, 'top':1.35}
        color : (1,0,0,.5)

    Label:
        text : "Focus"
        font_size : 15
        pos_hint : {'center_x': .5, 'center_y': .27}

    Slider:
        id : focus_slider
        value_track : True
        value_track_color : [1, 0, 0, 1]
        range : (20, 100)                                  #Range must be checked with camera Specs!
        value : 20
        step : 1
        pos_hint : {'center_x': .5, 'center_y': .25}
        size_hint_y : None
        height : 50
        on_value : root.focus_value = self.value

    Label:
        text : "Focus at %scm" % str(root.focus_value)
        font_size : 10
        pos_hint : {'center_x': .5, 'center_y': .22}

    LabelledSlider:
        pos_hint : {'center_x': .5, 'center_y': .18}
        propertyX:
            text : "Brightness"




<InteractiveGUI>:
    cameraview : cameraview
    controlsview : controlsview



    CameraView:
        id : cameraview
        size_hint_x : 4

    ControlsView:
        id : controlsview

here only the intersting parts:

<LabelledSlider>:

# The y-displacement relative to slider is +0.2 for "property" Label and -0.3 for "value" Label

    slider_value : slider.value
    property_name : property.text
    propertyX : property

    Label:
        id: property
        text: ""
        font_size : 15
        pos_hint_center_x : .5
        pos_hint_center_y : .7


    Slider:
        id : slider
        value_track : True
        value_track_color : [1, 0, 0, 1]
        range : (0, 100)                                  #Range must be checked with camera Specs!
        value : 0
        step : 1
        pos_hint_center_x : .5
        pos_hint_center_y : .5
        size_hint_y : None
        height : 50
        on_value : root.slider_value = self.value

    Label:
        text : "%(property)s at %(value)scm" % {"property" : root.property_name, "value" : str(root.slider_value)}
        font_size : 10
        pos_hint_center_x : .5
        pos_hint_center_y : .2


<ControlsView>:

    focus_value : focus_slider.value

    [...]

    LabelledSlider:
        pos_hint : {'center_x': .5, 'center_y': .18}
        propertyX:
            text : "Brightness"

And finally the python file:

import kivy
from kivy.properties import ObjectProperty

kivy.require('2.1.0')


from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.label import Label
from kivy.uix.camera import Camera
from kivy.uix.dropdown import DropDown
from kivy.base import runTouchApp
from kivy.uix.slider import Slider
from kivy.uix.screenmanager import ScreenManager


class InteractiveGUI(BoxLayout):
    cameraview = ObjectProperty(None)
    controlsview = ObjectProperty(None)


    def select_camera_button(self):
        if self.cameraview.playing_camera.index == 0:
            self.cameraview.playing_camera.index = 1
        else:
            self.cameraview.playing_camera.index = 0

    def select_camera(self, data):
        if str(data) == "Camera 1":
            self.cameraview.playing_camera.index = 0
        elif str(data) == "Camera 2":
            self.cameraview.playing_camera.index = 1
        elif str(data) == "Camera 3":
            self.cameraview.playing_camera.index = 2
        elif str(data) == "Camera 4":
            self.cameraview.playing_camera.index = 3
        else:
            pass


class CameraView(RelativeLayout):
    playing_camera = ObjectProperty(None)
    '''def change_camera(self):
        if (playing_camera.index == 0):
            playing_camera.index = 1
        else:
            playing_camera.index = 0'''

class ControlsView(RelativeLayout):
    playing_camera = ObjectProperty(None)

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

        # A dropdown Menu for camera selection needs to be implemented:
        # Define the Dropdown menu here in Python code, because it has a lot of logic behind

        self.camera_sel = DropDown()
        for index in range(1, 5):
            btn = Button(text='Camera %d' % index,
                         size_hint_x=.7,
                         size_hint_y=None,
                         height=25
                         )
            btn.bind(on_release=lambda btn: self.camera_sel.select(btn.text))
            self.camera_sel.add_widget(btn)

        self.mainbutton = Button(text='Select Camera',
                            size_hint_x=.7,
                            size_hint_y=None,
                            height=35,
                            pos_hint={'center_x': .5, 'center_y': .5}
                            )

        self.add_widget(self.mainbutton)
        self.mainbutton.bind(on_release = self.camera_sel.open)
        self.camera_sel.bind(on_select = lambda instance, x: setattr(self.mainbutton, 'text', x))
        self.camera_sel.bind(on_select = self.select_camera1)            #CAN'T CALL PARENT INSIDE __init()__

    def select_camera1(self, instance, data):
        print(self.parent)
        print(data)
        print(type(data))
        return self.parent.select_camera(data)



class LabelledSlider(Slider):
    pass




class CustomDropDown(DropDown):
    pass









class LogPortGUI_DropPython(App):
    def build(self):
        '''
        All the "simple" UI Design of the GUI can be found in the LogPort.kv file
        in this directory.
        In this GUI.py file will then remain only the logic, function defintion and
        smaller adjustement to maintain a better overview.

        :return: The main GUI of the App
        '''

        root = InteractiveGUI()

        print(root)
        print(root.children)
        for child in root.children:
            print("Now the 1 Level childrenn")
            print(child)
            for granchild in child.children:
                print("Now 2nd level Childrenn")
                print(granchild)

        return root


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

The Error message displys:

   File
"/Users/____/opt/anaconda3/lib/python3.7/site-packages/kivy/lang/parser.py",
line 194, in precompile
    self.co_value = compile(value, self.ctx.filename or '<string>', mode) 
File
"/Users/____/PycharmProjects/untitled/logportgui_droppython.kv", line
179
 text : "Brightness"
      ^  SyntaxError: invalid syntax

EDIT


John’s answer worked perfectly, but still the positioning of Labels on top and at the bottom of the slider doesn’t work correctly.

Changes in the code

  • Added John’s suggestion to get the property_Label.text to work

  • Changed the Inheritance of LabeledSlider to RelativeLayout (originally it was, wrognly, inheriting from the Slider class)

  • Changed the pos_hint_center_y to 1 and 0 respectively (idea was to put the first Label at the top of the LabelledSlider’s RelativeLayout and the value Slider at the bottom, to see if actually something would change.)

    class LabelledSlider(RelativeLayout):
    pass

LabelledSlider’s class definition:

<LabelledSlider>:

# The y-displacement relative to slider is +0.2 for "property" Label and -0.3 for "value" Label

    slider_value : slider.value
    property_name : property.text
    property_text : ""


    Label:
        id: property
        text: root.property_text
        size_hint : (1,.2)
        font_size : 15
        pos_hint_center_x : .5
        pos_hint_center_y : 1


    Slider:
        id : slider
        value_track : True
        value_track_color : [1, 0, 0, 1]
        range : (0, 100)                                  #Range must be checked with camera Specs!
        value : 0
        step : 1
        pos_hint_center_x : .5
        pos_hint_center_y : .5
        size_hint_y : None
        height : 50
        on_value : root.slider_value = self.value

    Label:
        text : "%(property)s at %(value)scm" % {"property" : root.property_name, "value" : str(root.slider_value)}
        font_size : 10
        size_hint : (1,.2)
        pos_hint_center_x : .5
        pos_hint_center_y : 0

And then add the sliders as children of Controlsview (another RelativeLayout):

<ControlsView>:

    focus_value : focus_slider.value
    Label:
        text : "Focus"
        font_size : 15
        pos_hint : {'center_x': .5, 'center_y': .27}

    Slider:
        id : focus_slider
        value_track : True
        value_track_color : [1, 0, 0, 1]
        range : (20, 100)                                  #Range must be checked with camera Specs!
        value : 20
        step : 1
        pos_hint : {'center_x': .5, 'center_y': .25}
        size_hint_y : None
        height : 50
        on_value : root.focus_value = self.value

    Label:
        text : "Focus at %scm" % str(root.focus_value)
        font_size : 10
        pos_hint : {'center_x': .5, 'center_y': .22}

    LabelledSlider:
        id : brightness_slider
        size_hint : (1, 0.2)
        pos_hint : {'center_x': .5, 'center_y': .47}
        property_text : "Brightness"

    LabelledSlider:
        id : other_slider
        size_hint : (1, 0.2)
        pos_hint : {'center_x': .5, 'center_y': .40}
        property_text : "Other"

The croocked Output looks like this:

enter image description here

Asked By: Bonito

||

Answers:

Try adding a Property to the LabelledSlider. You can do this in the kv:

<LabelledSlider>:

# The y-displacement relative to slider is +0.2 for "property" Label and -0.3 for "value" Label

    slider_value : slider.value
    property_name : property.text
    propertyX : property
    property_text: ''  # new property

    Label:
        id: property
        text: root.property_text  # use the new property here
        font_size : 15
        pos_hint_center_x : .5
        pos_hint_center_y : .7

Then you can set that property like this:

LabelledSlider:
    pos_hint : {'center_x': .5, 'center_y': .18}
    property_text: "Brightness"
Answered By: John Anderson
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.