如何使用 kv 文件刷新 Kivy 中的 GridLayout

问题描述

我需要帮助。

我使用 Kivy 创建了一个小型移动应用程序。

我有两个屏幕:ScreenList 和 ScreenDetail。

但是包含 GridLayout 的屏幕(ScreenList)不会刷新

ScreenList:包含项目列表

ScreenDetail:包含单个项目的详细信息。

应用的工作原理:

  1. 当我点击按钮 1 上的第一项时
  2. 我会转到该项目的详细信息。
  3. 我修改了第二个字段。我将文本:Firt element 替换为 First and update data
  4. 录制后,我将应用程序重定向到包含 (ScreenList) 元素列表的屏幕。
  5. 但元素列表保持不变,则数据库中的数据已被修改。 6.当我返回包含详细信息的屏幕 (ScreenDetail) 时,我看到数据已更新。

如何刷新 ScreenList 中的项目列表?

这里以图片为例

更新前的列表

enter image description here

更新前

enter image description here

更新后

enter image description here

更新后的列表

enter image description here

这是python代码:

import kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.properties import ObjectProperty,StringProperty
from kivy.lang import Builder
from kivymd.uix.picker import MDTimePicker
from kivymd.uix.picker import MDDatePicker
from kivymd.app import MDApp
import sqlite3
import os.path

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
db_path = os.path.join(BASE_DIR,"donnee/ProjetMaison.db")


def donnee_dic(cursor,row):
    d = {}
    for idx,col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

cur_id = None

class ScreenList(Screen):
    data_grid = ObjectProperty()
    
    def go_to_detail(self,instance):
        global cur_id
        cur_id = int(instance.text)
        self.manager.current = 'screen_detail'
    
    def __init__(self,**kwargs):
        super(ScreenList,self).__init__(**kwargs)
        
        con_list_course = sqlite3.connect(db_path)
        con_list_course.row_factory = donnee_dic
        curss_list_course = con_list_course.cursor()
        data_list_course = curss_list_course.execute("select  * FROM courses")
        self.data_grid.bind(minimum_height=self.data_grid.setter('height'))
        for row in data_list_course:
            template_screen = GridLayout(cols=2,size_hint_y=None,height=40)           
            template_screen.add_widget(Label(text=row['nom']))
            template_screen.add_widget(Button(text=str(row['id']),on_press=self.go_to_detail))
            
            self.data_grid.add_widget(template_screen)

        con_list_course.close()


def Maj_colonne(id,nom):
    try:
        sqliteConnection = sqlite3.connect(db_path)
        cursor = sqliteConnection.cursor()
        sqlite_update_query = """Update courses set nom = ?  where id = ?"""
        columnValues = (nom,id)
        cursor.execute(sqlite_update_query,columnValues)
        sqliteConnection.commit()
        sqliteConnection.commit()
        cursor.close()

    except sqlite3.Error as error:
        print("Erreur de connexion",error)
    finally:
        if sqliteConnection:
            sqliteConnection.close()

class ScreenDetail(Screen):
    label_id = ObjectProperty()
    label_nom = ObjectProperty()
    
    def __init__(self,**kwargs):
        super(ScreenDetail,self).__init__(**kwargs)
        
    def on_enter(self):
        global cur_id
        conn = sqlite3.connect(db_path)

        cursor = conn.execute("select  * FROM courses where id=?",str(cur_id))
        for row in cursor:      
            self.label_id.text = str(row[0])
            self.label_nom.text = str(row[1])

        cursor.close()


    def update_course(self):
        id_pk = self.ids['label_id'].text
        nom = self.ids['label_nom'].text        
        if id_pk:
            Maj_colonne(str(id_pk),str(nom))
            self.ids['label_id'].text = ''
            self.ids['label_nom'].text = ''
            self.manager.current = 'screen_list'        

class Listapp(MDApp):
    def build(self):
        screenmanager = ScreenManager()
        screenmanager.add_widget(ScreenList(name='screen_list'))
        screenmanager.add_widget(ScreenDetail(name='screen_detail'))
        
        return screenmanager

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

这里是 kv 代码:

#:import utils kivy.utils                    
<ScreenList>:
    data_grid: data_grid
    MDBoxLayout:
        orientation: 'vertical'
        md_bg_color: app.theme_cls.primary_color
        radius: [25,0]   
        ScrollView:
            MDGridLayout:
                id: data_grid
                cols: 1
                spacing:10
                size_hint_y:None
                
<ScreenDetail>:
    label_id: label_id
    label_nom: label_nom
    MDBoxLayout:
        orientation: 'vertical'
        md_bg_color: app.theme_cls.primary_color
        ScrollView:
            GridLayout:
                id: detail_grid
                cols:2          
                Label:
                    text: 'Numéro:'
                    bold: True
                TextInput:
                    id: label_id
                    text: ''                
                Label:
                    text: 'Nom:'
                    bold: True
                TextInput:
                    id: label_nom
                    text: ''
                Button:
                    text: 'OK'
                    size_hint_y: None
                    on_press: root.update_course() 

谢谢

解决方法

一般来说,与 Kivy 一起工作时需要注意的几点

  • 当您尝试在屏幕之间共享数据时,使用 app 方法而不是屏幕的特定方法通常很有用。

  • 当您需要创建大量按钮时,可能在循环内,并在其事件(on_presson_release)上绑定方法时,在飞行并绑定其事件的方法,因为您需要做额外的工作以确保在触发事件时使用正确的参数调用这些绑定方法。而是创建一个自定义类模板并使用它。

您的问题的有效解决方案(仅显示已添加/更新的部分

创建自定义GridLayout:

class MyGrid(GridLayout):
    pass

更新了 __init__ 中的 ScreenList 方法:

   def __init__(self,**kwargs):
        #...
        app = MDApp.get_running_app()
        for row in data_list_course:
            template_screen = MyGrid()
            template_screen.ids.lbl.text = row['nom']
            template_screen.ids.btn.text = str(row['id'])
            
            self.data_grid.add_widget(template_screen)

app 类中添加的方法:

class Listapp(MDApp):
    def build(self):
        self.screenmanager = ScreenManager()
        self.screenmanager.add_widget(ScreenList(name='screen_list'))
        self.screenmanager.add_widget(ScreenDetail(name='screen_detail'))
        
        return self.screenmanager
    
    def go_to_detail_(self,inst):
        self.inst = inst
        self.screenmanager.current = 'screen_detail'
    
    def update_course_(self,label_id,label_nom):
        c = self.inst.children[::-1]
        c[0].text = label_nom.text
        c[1].text = label_id.text
        print(label_id.text,label_nom.text)        
        if label_id.text:
            Maj_colonne(str(id_pk),str(nom))
            label_nom.text = ''
            label_id.text = ''
            self.screenmanager.current = 'screen_list'

这是更新后的 kv 代码:

#:import utils kivy.utils                    
<ScreenList>:
    data_grid: data_grid
    MDBoxLayout:
        orientation: 'vertical'
        md_bg_color: app.theme_cls.primary_color
        radius: [25,0]   
        ScrollView:
            MDGridLayout:
                id: data_grid
                cols: 1
                spacing:10
                size_hint_y:None
                
<ScreenDetail>:
    label_id: label_id
    label_nom: label_nom
    MDBoxLayout:
        orientation: 'vertical'
        md_bg_color: app.theme_cls.primary_color
        ScrollView:
            GridLayout:
                id: detail_grid
                cols:2          
                Label:
                    text: 'Numéro:'
                    bold: True
                TextInput:
                    id: label_id
                    text: ''                
                Label:
                    text: 'Nom:'
                    bold: True
                TextInput:
                    id: label_nom
                    text: ''
                Button:
                    text: 'OK'
                    size_hint_y: None
                    on_press: app.update_course_(label_id,label_nom)

<MyGrid>:
    cols:2
    size_hint_y:None
    height:40
    
    Label:
        id: lbl
        text: ''
    
    Button:
        id: btn
        text: ''
        on_press:
            app.go_to_detail_(root)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...