Shin euichul
Shin euichul

Reputation: 63

kivyMD intermittent AssertionError

kivy 2.0.0, kivymd 0.104.2dev0, python3.7

I am having error intermittently when I add MDdatatable to new screen's MDBoxLayout with button press.

sometime get error immediately, sometime get error once out of 30 times of try.

AssertionError with .py and KeyError: <ParserRule name='<CommonElevationBehavior>'> with apk.

any one have idea where should I look?

and also have this warning too, intermittently, with button press.

[WARNING] <kivymd.uix.gridlayout.MDGridLayout object at 0x00000290BDE1D278> have no cols or rows set, layout is not triggered.

even if my all gridlayout have cols set.

here is my minimal code.

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.metrics import dp
import threading, time

KV = """
   
ScreenManager:
    id : scr_mng  
    Ad_control_main_screen:
    Ad_control_detail:
    
<Ad_control_main_screen>:
    id: ad_control_main_screen
    name: 'ad_control_main_screen'
    MDFillRoundFlatButton
        text: 'detail' 
        pos_hint: {"center_x": 0.5, "center_y": 0.5}
        on_release:
            root.Adctr_detail()
   
<Ad_control_detail>
    id: ad_control_detail  
    name: "ad_control_detail"  
    
    MDBoxLayout:
        orientation: "vertical"
        MDBoxLayout:
            height: self.minimum_height
            size_hint_y: None
            AnchorLayout:
                anchor_x: "center"
                anchor_y: "center"
                size_hint_y: None
                padding: [0, 5, 0, 0]
                
                MDGridLayout:
                    cols: 1
                    spacing: [10, 12]
                    size_hint: None, None
                    height: self.minimum_height
                    width: self.minimum_width                
                
                    MDFillRoundFlatButton:
                        text: "back"
                        on_release:
                            root.get_back()
        MDBoxLayout:
            id: table_layout
   
"""

class Ad_control_main_screen(Screen):
    def on_enter(self, *args):
        global scr_mng
        scr_mng = self.manager
        scr_mng.transition.direction = 'left'

    def Adctr_detail(self):
        scr_mng.current = 'ad_control_detail'

class Ad_control_detail(Screen):
    def on_enter(self, *args):
        if self.ids.table_layout.children != []:
            self.ids.table_layout.clear_widgets()
        self.get_camData_thread()

    def get_camData_thread(self):
        get_cam_data = threading.Thread(target=self.create_table)
        get_cam_data.daemon = True
        get_cam_data.start()

    def create_table(self, *args):
        time.sleep(1)
        r_data = []
        for i in range(10):
            r_data.append((i, "data "+str(i), "data "+str(i), "data "+str(i), "data "+str(i), "data "+str(i)))

        c_data = [("", dp(5)),
                  ("colum 1", dp(30)),
                  ("colum 2", dp(15)),
                  ("colum 3", dp(15)),
                  ("colum 4", dp(15)),
                  ("colum 5", dp(15)),]

        data_table = MDDataTable(
            use_pagination=False,
            check=False,
            elevation=0,
            column_data=c_data,
            row_data=r_data,
            rows_num=int(len(r_data))
        )
        self.ids.table_layout.add_widget(data_table)

    def get_back(self):
        scr_mng.transition.direction = 'right'
        scr_mng.current = 'ad_control_main_screen'

sm = ScreenManager()
sm.add_widget(Ad_control_main_screen(name='ad_control_main_screen'))
sm.add_widget(Ad_control_detail(name='ad_control_detail'))

class Test(MDApp):
    def build(self):
        return Builder.load_string(KV)


Test().run()

Upvotes: 0

Views: 122

Answers (2)

John Anderson
John Anderson

Reputation: 39117

To use the thread, you must limit what you do in that thread. Some operations must be performed on the main thread. Here is a modified version of your Ad_control_detail class that does that:

class Ad_control_detail(Screen):
    def on_enter(self, *args):
        if self.ids.table_layout.children != []:
            self.ids.table_layout.clear_widgets()
        self.get_camData_thread()

    def get_camData_thread(self):
        get_cam_data = threading.Thread(target=self.create_table)
        get_cam_data.daemon = True
        get_cam_data.start()

    def add_table(self, r_data, c_data, dt):
        # This does the operations that must be on the main thread
        data_table = MDDataTable(
            use_pagination=False,
            check=False,
            column_data=c_data,
            row_data=r_data,
            rows_num=int(len(r_data))
        )
        self.ids.table_layout.add_widget(data_table)

    def create_table(self, *args):
        # this does the operations that may be done on another thread
        time.sleep(1)
        r_data = []
        for i in range(10):
            r_data.append((i, "data " + str(i), "data " + str(i), "data " + str(i), "data " + str(i), "data " + str(i)))

        c_data = [("", dp(5)),
                  ("colum 1", dp(30)),
                  ("colum 2", dp(15)),
                  ("colum 3", dp(15)),
                  ("colum 4", dp(15)),
                  ("colum 5", dp(15)), ]
        
        # run the add_table() method on the main thread
        Clock.schedule_once(partial(self.add_table, r_data, c_data))

    def get_back(self):
        scr_mng.transition.direction = 'right'
        scr_mng.current = 'ad_control_main_screen'

Upvotes: 1

John Anderson
John Anderson

Reputation: 39117

I believe the problem is that you are making changes to the GUI on a thread other than the main thread. Try changing:

class Ad_control_detail(Screen):
    def on_enter(self, *args):
        if self.ids.table_layout.children != []:
            self.ids.table_layout.clear_widgets()
        self.get_camData_thread()

to:

class Ad_control_detail(Screen):
    def on_enter(self, *args):
        if self.ids.table_layout.children != []:
            self.ids.table_layout.clear_widgets()
        # self.get_camData_thread()
        self.create_table()

I think you also need to remove elevation=0, from the MDDataTable creation command.

Upvotes: 1

Related Questions