How to import and instantiate (with keyword arguments) custom made class of Python KivyMD?

Question:

I am trying to learn KivyMD and Python. So, I am fairly new to KivyMD. I have made something like a card (like MDCard) in kivyMD. I am trying to import it to my other application and instanciate it with some arguments. But I am unable to do so. Here is what my code looks like for now.

Filename – finaltile.py

from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty, ListProperty, ColorProperty


class MyTileItem(MDBoxLayout):

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

        self.box_color = ListProperty()
        self.heading_name = StringProperty()
        self.heading_color = ColorProperty('#d31010')
        self.sub_heading_1 = StringProperty()
        self.sub_heading_2 = StringProperty()
        self.sub_heading_color = ColorProperty('#d31010')
        self.time_duration = StringProperty()
        self.time_duration_color = ColorProperty('#d31010')
        

    

And its .kv file looks like this:
Filename – finaltile.kv
Both the file is in the same directory.

<MyTileItem>:

    orientation: "vertical"
    MDBoxLayout:
        padding: (sp(10), sp(6), sp(10), sp(10))
        # opacity: .5
        size_hint:1, None
        height: sp(100)
        canvas.before:
            Color: 
                rgba: root.box_color
            RoundedRectangle:
                pos: self.pos
                size: self.size
                radius: [sp(20), sp(20), sp(20), sp(20)]
        MDGridLayout:
            rows: 2
            spacing: sp(5)
            MDLabel:

                text: "This is a heading"
                halign: 'left'
                # valign: 'center'
                font_size: sp(18)
                color: root.heading_color
                bold: True

            MDBoxLayout:
                
                MDBoxLayout:
                    size_hint_x: .6
                    orientation: 'vertical'
                    MDLabel:
                        text: root.sub_heading_1
                        font_size: sp(15)
                        color: root.sub_heading_color
                        bold: True
                        halign: 'left'

                    MDLabel:
                        text: root.sub_heading_2
                        halign: 'left'
                        font_size: sp(15)
                        color: root.sub_heading_color
                        bold: True


                MDLabel:
                    size_hint_x: .4
                    text: str(root.time_duration)
                    color: root.time_duration_color
                    halign: 'right'
                    font_size: sp(25)
                    bold: True
    Widget:

Now, I want to do this in some other python file:

from finaltile import MyTileItem 
# The Class I want to import and instantiate with available data (like box_color, heading_name, sub_heading_1, sub_heading_2, sub_heading_color, time_duration_color)
from kivymd.app import MDApp
from kivymd.uix.scrollview import ScrollView
from kivy.lang import Builder
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.gridlayout import MDGridLayout

class MyTile(MDBoxLayout):
    pass

class NewTileItem(MyTileItem):
    pass

class TestApp(MDApp):
    def build(self):

        self.theme_cls.primary_palette = "BlueGray"
        self.theme_cls.primary_hue = '800'
        self.theme_cls.theme_style = "Dark"
        self.myview = MyTile()
        
        self.myItem = NewTileItem(box_color = (1, 1, 1, 0.5), heading_name = "This is heading 1.", heading_color = (1, 0, 0, 1), sub_heading_1 = "This is the sub heading 1", sub_heading_2 = "This is sub heading 2", sub_heading_color = (0, 1, 0, 1), time_duration = "01:02:03", time_duration_color = (0, 0, 1, 1))
        self.myview.add_widget(self.myItem)
        self.myItem = NewTileItem(box_color = (1, 1, 1, 0.5), heading_name = "This is heading 2.", heading_color = (1, 0, 0, 1), sub_heading_1 = "This is the sub heading 1", sub_heading_2 = "This is sub heading 2", sub_heading_color = (0, 1, 0, 1), time_duration = "01:02:03", time_duration_color = (0, 0, 1, 1))
        self.myview.add_widget(self.myItem)
        
        return self.myview

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

And the ‘test.kv’ file looks something like this:

#:import MyTileItem finaltile.MyTileItem


<MyTile>:
    
    orientation: 'vertical'
    size_hint: 1, None
    ScrollView:
        MDBoxLayout:
            id: box
            orientation: 'vertical'
            spacing: sp(110)
            padding: sp(20), sp(200)
            size_hint_y: None
            height: self.minimum_height
            NewTileItem:
            NewTileItem:
            NewTileItem:
            NewTileItem:
            NewTileItem:
            NewTileItem:

I want to be able to import the ‘MyTileItem’ class and use it multiple times in different projects. How can I do this? I have searched everywhere and nothing seems to do it for me. Here is an image of what I am trying to achieve.

enter image description here

The Error/Issues I am currently getting is this:

  • First, I have a blank screen, which when I try to close, gives me the actual screen I am trying to achieve. (I have no idea why that is happening.
  • And then I am getting this the under-written error multiple times when I close the window.
  • And I would like to point again that the window closes when I close it twice. First, I get a blank screen, try to close it, which then gives me the actual window. And then when I close it. The window closes and the under-written error pops up like 100 times in a go. The error is:
Traceback (most recent call last):
   File "kivygraphicsshader.pyx", line 245, in kivy.graphics.shader.Shader.set_uniform
   File "kivygraphicsshader.pyx", line 284, in kivy.graphics.shader.Shader.upload_uniform
 IndexError: list index out of range
 Exception ignored in: 'kivy.graphics.instructions.RenderContext.set_state'
 Traceback (most recent call last):
   File "kivygraphicsshader.pyx", line 245, in kivy.graphics.shader.Shader.set_uniform
   File "kivygraphicsshader.pyx", line 284, in kivy.graphics.shader.Shader.upload_uniform
 IndexError: list index out of range
Asked By: Aaron Jones

||

Answers:

The errors you are getting are caused by not defining the default value for box_color in your MyTileItem class. That results in the NewTileItem widgets that are created by the test.kv file having a box_color of [].

The fix is to modify the finaltile.py class, something like this:

from kivy.lang import Builder
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty, ListProperty, ColorProperty


Builder.load_file('finaltile.kv')


class MyTileItem(MDBoxLayout):
        box_color = ListProperty((1, 1, 0, 0.5))
        heading_name = StringProperty()
        heading_color = ColorProperty('#d31010')
        sub_heading_1 = StringProperty()
        sub_heading_2 = StringProperty()
        sub_heading_color = ColorProperty('#d31010')
        time_duration = StringProperty()
        time_duration_color = ColorProperty('#d31010')

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

Note that the Properties must be defined in the class, but outside of any method. Also, I added a call to load the finaltile.kv file.

Also, in the text.kv file, the line:

size_hint: 1, None

should be removed.

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.