kivyMD 间歇性断言错误

kivyMD intermittent AssertionError

kivy 2.0.0,kivymd 0.104.2dev0,python3.7

当我通过按下按钮将 MDdatatable 添加到新屏幕的 MDBoxLayout 时,间歇性地出现错误。

有时立即出错,有时尝试 30 次后出错一次。

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

有人知道我应该去哪里看吗?

也有此警告,间歇性地,按下按钮。

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

即使我所有的网格布局都设置了列。

这是我的最小代码。

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()

我认为问题在于您正在主线程以外的线程上更改 GUI。尝试更改:

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()

至:

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()

我认为您还需要从 MDDataTable 创建命令中删除 elevation=0,

要使用线程,您必须限制在该线程中执行的操作。有些操作必须在主线程上执行。这是您的 Ad_control_detail class 的修改版本:

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'