代码之家  ›  专栏  ›  技术社区  ›  Berch

如何从sqlite db中检索数据并设置为kivy textinput字段?

  •  0
  • Berch  · 技术社区  · 7 年前

    我通过从Kivy文档和其他在线资源制作小应用程序来学习Kivy。当前代码有 两个文本输入字段(userid、username)用于将值存储在数据库中,使用recycleview将显示存储的数据。 使用Kivy图形用户界面的按钮。

    在按钮按下时,我需要将来自数据库的相应数据设置到相应的文本输入字段。即打开 按userid为1的按钮,文本输入字段应显示该行的userid和用户名值。

    主.py

    import sqlite3
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.recycleview.views import RecycleDataViewBehavior
    from kivy.uix.button import Button
    from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
    from kivy.uix.recyclegridlayout import RecycleGridLayout
    from kivy.uix.behaviors import FocusBehavior
    from kivy.uix.recycleview.layout import LayoutSelectionBehavior
    
    class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
                                      RecycleGridLayout):
        ''' Adds selection and focus behaviour to the view. '''
    
    
    class SelectableButton(RecycleDataViewBehavior, Button):
        ''' Add selection support to the Button '''
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
    
        def refresh_view_attrs(self, rv, index, data):
            ''' Catch and handle the view changes '''
            self.index = index
            return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
    
        def on_touch_down(self, touch):
            ''' Add selection on touch down '''
            if super(SelectableButton, self).on_touch_down(touch):
                return True
            if self.collide_point(*touch.pos) and self.selectable:
                return self.parent.select_with_touch(self.index, touch)
    
        def apply_selection(self, rv, index, is_selected):
            ''' Respond to the selection of items in the view. '''
            self.selected = is_selected
    
    class RV(BoxLayout):
        ''' Creates Db conn, table, and saves data, retrives stored data and
        displays in the RecycleView .'''
        data_items = ListProperty([])
    
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            self.create_table()
            self.get_users()
    
        def create_table(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
            sql = """CREATE TABLE IF NOT EXISTS Users(
            UserID integer PRIMAY KEY,
            UserName text NOT NULL)"""
            cursor.execute(sql)
            connection.close()
    
        def get_users(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
    
            cursor.execute("SELECT * FROM Users ORDER BY UserID ASC")
            rows = cursor.fetchall()
    
            # create data_items
            for row in rows:
                for col in row:
                    self.data_items.append(col)
    
        def save(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
    
            UserID = self.ids.no.text
            UserName = self.ids.name.text
    
            try:
                save_sql="INSERT INTO Users (UserID, UserName) VALUES (?,?)"
                connection.execute(save_sql,(UserID, UserName))
                connection.commit()
                connection.close()
            except sqlite3.IntegrityError as e:
                print("Error: ",e)
    
    class TestApp(App):
        title = "Kivy RecycleView & SQLite3 Demo"
    
        def build(self):
            return RV()
    
    
    if __name__ == "__main__":
        TestApp().run()
    

    测试.kv

    #:kivy 1.10.0
    <TextInputPopup>:
        title: "Popup"
        size_hint: None, None
        size: 400, 400
        auto_dismiss: False
    
        BoxLayout:
            orientation: "vertical"
            TextInput:
                id: txtinput
                text: root.obj_text
            Button:
                size_hint: 1, 0.2
                text: "Save Changes"
                on_release:
                    root.obj.update_changes(txtinput.text)
                    root.dismiss()
            Button:
                size_hint: 1, 0.2
                text: "Cancel Changes"
                on_release: root.dismiss()
    
    
    <SelectableButton>:
        # Draw a background to indicate selection
        canvas.before:
            Color:
                rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    
    <RV>:
        BoxLayout:
            orientation: "vertical"
            user_no_text_input: no
            user_name_text_input: name
    
            Label:
                text: "USER NUMBER"
                size_hint: (.5, None)
                height: 30
            TextInput:
                id: no
                size_hint: (.5, None)
                height: 30
                multiline: False
            Label:
                text: "USER NAME"
                size_hint: (.5, None)
                height: 30
            TextInput:
                id: name
                size_hint: (.5, None)
                height: 30
                multiline: False
            Button:
                id: save_btn
                text: "SAVE BUTTON"
                height: 50
                width: 100
                on_press: root.save()
    
            GridLayout:
                size_hint: 1, None
                size_hint_y: None
                height: 25
                cols: 2
    
                Label:
                    text: "User ID"
                Label:
                    text: "User Name"
    
            BoxLayout:
                RecycleView:
                    viewclass: 'SelectableButton'
                    data: [{'text': str(x)} for x in root.data_items]
                    SelectableRecycleGridLayout:
                        cols: 2
                        default_size: None, dp(26)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        orientation: 'vertical'
                        multiselect: True
                        touch_multiselect: True
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   ikolim    7 年前

    解决方案

    解决方案如下:有关详细信息,请参阅代码段、示例和输出。

    Kv文件

    1. 添加 on ou press event under class rule, <selectablebutton>: 。当on-press event is fire时,它将调用 root.on-press(self) method in the root class, rv ,and pass an instance of the button. , self.
    2. 将两个objecproperty挂钩( user_no_text_input:no , user_name_text_input:name )移动到右侧位置i.e.from under boxlayout: to <rv>:
    3. 替换 data:['text':str(x)for x in root.data_items] with data:root.data_items

    代码段-kv

    <selectablebutton>:
    …
    按下:
    app.root.on_-press(自我)
    
    <RV>:
    用户输入:否
    用户名\文本\输入:名称
    
    方框布局:
    方向:“垂直”
    
    标签:
    …
    
    方框布局:
    回收视图:
    viewClass:'可选择按钮'
    数据:root.data_items
    可选择的回收布局:
    

    python代码

    在RV类中,执行以下操作:

    1. 为kivy.properties添加导入语句numericproperty.
    2. 添加objecpropertyforuser_no_text_input=objectproperty(none)anduser_name_text_input=objectproperty(none)
    3. total_col_headings=numericproperty(0)
    4. 创建一个on_press().method for theon_press.event.
    5. 创建一个get_table_column_headings()方法来获取表中的总列标题。这用于创建列范围。
    6. enhanceget_users()method,to create a list with db column value,db primary key value,and db column range.使用数据库列范围的诀窍是用单击/按下的行中的值填充textinputwidgets。

    代码段-python

    from kivy.properties import booleanproperty,listproperty,numericproperty,objectproperty
    …
    
    RV类(箱布局):
    ''创建db conn,table,并保存数据,检索存储的数据和
    在RecycleView中显示。“”
    data_items=listproperty([])
    user_no_text_input=objectProperty(无)
    user_name_text_input=对象属性(无)
    总列标题=数字属性(0)
    
    定义初始化(self,**kwargs):
    super(RV,self)。初始化(*kwargs)
    self.create_table()。
    self.get_table_column_headings()。
    self.get_用户()
    
    def on ou press(self,instance):
    columns=self.data_items[instance.index]['range']
    self.user_no_text_input.text=self.data_items[列[0]]['text']
    self.user_name_text_input.text=self.data_items[列[1]]['text']
    
    def get_table_column_标题(self):
    连接=sqlite3.connect(“demo.db”)
    
    带连接:
    #通过WITH关键字,python解释器自动释放资源。
    #它还提供错误处理
    cursor=connection.cursor()。
    cursor.execute(“pragma table_info(users)”)
    col_headings=cursor.fetchall()。
    self.total_col_headings=len(col_headings)
    …
    
    def获取用户(self):
    连接=sqlite3.connect(“demo.db”)
    cursor=connection.cursor()。
    
    cursor.execute(“select*from users order by userid asc”)。
    rows=cursor.fetchall()。
    
    #使用db列、db主键和db列范围创建列表
    数据=[]
    低=0
    高=自总列标题-1
    
    对于行中的行:
    对于行中的列:
    data.append([列,行[0],[低,高]])
    低+=自总列标题
    高+=自总列标题
    
    #创建数据项
    self.data_items=['text':str(x[0]),'index':str(x[1]),'range':x[2]for x in data]
    

    示例

    主要.py

    导入sqlite3
    来自kivy.app导入应用程序
    从kivy.uix.boxlayout导入boxlayout
    从kivy.uix.recycleView.views导入recycledataviewBehavior
    从kivy.uix.button导入按钮
    从kivy.properties导入booleanproperty、listproperty、numericproperty、objectproperty
    从kivy.uix.recyclegridlayout导入recyclegridlayout
    从kivy.uix.behaviors导入FocusBehavior
    从kivy.uix.recycleView.layout导入布局选择行为
    
    
    类selectable recyclegridlayout(FocusBehavior、LayoutSelectionBehavior、
    回收布局):
    “将选择和焦点行为添加到视图中。”
    
    
    类SelectableButton(RecycledataViewBehavior,Button):
    ''将选择支持添加到按钮'''
    索引=无
    选定=布尔属性(假)
    可选=布尔属性(真)
    
    def刷新视图属性(self、rv、index、data):
    “'捕获并处理视图更改”“”
    self.index=索引
    返回super(selectablebutton,self)。刷新视图属性(rv,index,data)
    
    def on ou touch ou down(自我,触摸):
    “‘触摸屏下添加选择’”
    如果是super(selectable button,self),则按“向下”(touch)键:
    返回true
    如果self.collide ou point(*touch.pos)和self.select:
    返回self.parent.select\u touch(self.index,touch)
    
    def应用\选择(self、rv、index、is \选择):
    “响应视图中项目的选择。”
    self.selected=已选择
    
    
    RV类(箱布局):
    ''创建db conn,table,并保存数据,检索存储的数据和
    在RecycleView中显示。“”
    data_items=listproperty([])
    user_no_text_input=objectProperty(无)
    user_name_text_input=对象属性(无)
    总列标题=数字属性(0)
    
    定义初始化(self,**kwargs):
    super(RV,self)。初始化(*kwargs)
    self.create_table()。
    self.get_table_column_headings()。
    self.get_用户()
    
    def on ou press(self,instance):
    columns=self.data_items[instance.index]['range']
    self.user_no_text_input.text=self.data_items[列[0]]['text']
    self.user_name_text_input.text=self.data_items[列[1]]['text']
    
    def get_table_column_标题(self):
    连接=sqlite3.connect(“demo.db”)
    
    带连接:
    #通过WITH关键字,python解释器自动释放资源。
    #它还提供错误处理
    cursor=connection.cursor()。
    cursor.execute(“pragma table_info(users)”)
    col_headings=cursor.fetchall()。
    self.total_col_headings=len(col_headings)
    
    def创建表格(self):
    连接=sqlite3.connect(“demo.db”)
    cursor=connection.cursor()。
    如果不存在,则创建表用户(
    userid整数主键,
    用户名文本不为空)“”
    cursor.execute(SQL)
    连接。关闭()
    
    def获取用户(self):
    连接=sqlite3.connect(“demo.db”)
    cursor=connection.cursor()。
    
    cursor.execute(“select*from users order by userid asc”)。
    rows=cursor.fetchall()。
    
    #使用db列、db主键和db列范围创建列表
    数据=[]
    低=0
    高=自总列标题-1
    
    对于行中的行:
    对于行中的列:
    data.append([列,行[0],[低,高]])
    低+=自总列标题
    高+=自总列标题
    
    #创建数据项
    self.data_items=['text':str(x[0]),'index':str(x[1]),'range':x[2]for x in data]
    
    定义保存(自身):
    连接=sqlite3.connect(“demo.db”)
    cursor=connection.cursor()。
    
    userid=self.user_no_text_input.text
    用户名=self.user_name_text_input.text
    
    尝试:
    save_sql=“insert into users(userid,username)values(?)?)
    cursor.execute(save_sql,(userid,username))。
    连接.commit())
    连接。关闭()
    除了sqlite3.integrityerror as e:
    打印(“错误:”,E)
    
    
    类testapp(app):
    title=“Kivy RecycleView&sqlite3演示”
    
    定义构建(自身):
    返回RV()
    
    
    如果“名称”,
    testapp().run()。
    

    试验.kv

    :kivy 1.11.0
    
    <可选择按钮>:
    #绘制背景以指示所选内容
    画布。之前:
    颜色:
    rgba:(.0,0.9,.1,.3)如果self.selected,则为else(0,0,0,1)
    矩形:
    位置:self.pos
    大小:self.size
    按下:
    app.root.on_-press(自我)
    
    <RV>:
    用户输入:否
    用户名\文本\输入:名称
    
    方框布局:
    方向:“垂直”
    
    标签:
    文本:“用户编号”
    大小提示:(.5,无)
    高度:30
    文本输入:
    身份证:不
    大小提示:(.5,无)
    高度:30
    多行:假
    标签:
    文本:“用户名”
    大小提示:(.5,无)
    高度:30
    文本输入:
    ID:名称
    大小提示:(.5,无)
    高度:30
    多行:假
    按钮:
    ID:保存
    文本:“保存按钮”
    高度:50
    宽度:100
    按:root.save()。
    
    网格布局:
    大小提示:1,无
    大小提示:无
    高度:25
    科尔斯:2
    
    标签:
    文本:“用户ID”
    标签:
    文本:“用户名”
    
    方框布局:
    回收视图:
    viewClass:'可选择按钮'
    数据:root.data_items
    可选择的回收布局:
    科尔斯:2
    默认尺寸:无,dp(26)
    默认\大小\提示:1,无
    大小提示:无
    高度:自身最小高度
    方向:“垂直”
    多重选择:真
    触摸多选:真
    

    输出

  • 添加on_press类规则下的事件,<SelectableButton>:. 当on-press事件为fire时,它将调用root.on_press(self)根类中的方法,右心室,并传递按钮,self.
  • 移动两个操作钩(user_no_text_input: no,user_name_text_input: name)到正确的位置,即从下面BoxLayout:<RV>:.
  • 更换data: [{'text': str(x)} for x in root.data_items]具有data: root.data_items
  • 代码段-kv

    <SelectableButton>:
        ...
        on_press:
            app.root.on_press(self)
    
    <RV>:
        user_no_text_input: no
        user_name_text_input: name
    
        BoxLayout:
            orientation: "vertical"
    
            Label:
            ...
    
            BoxLayout:
                RecycleView:
                    viewclass: 'SelectableButton'
                    data: root.data_items
                    SelectableRecycleGridLayout:
    

    python代码

    在RV类中,执行以下操作:

    1. 添加NumericProperty为kivy.properties导入语句。
    2. 添加目标属性对于user_no_text_input = ObjectProperty(None)user_name_text_input = ObjectProperty(None)
    3. 添加数字属性对于total_col_headings = NumericProperty(0)
    4. 创建on_press()的方法按下事件。
    5. 创建get_table_column_headings()方法获取表中的列标题总数。用于创建列范围。
    6. 增强get_users()方法,创建具有db列值、db主键值和db列范围的列表。使用数据库列范围的技巧是填充文本输入框单击/按下行中的值的小部件。

    代码段-python

    from kivy.properties import BooleanProperty, ListProperty, NumericProperty, ObjectProperty
    ...
    
    class RV(BoxLayout):
        ''' Creates Db conn, table, and saves data, retrives stored data and
        displays in the RecycleView .'''
        data_items = ListProperty([])
        user_no_text_input = ObjectProperty(None)
        user_name_text_input = ObjectProperty(None)
        total_col_headings = NumericProperty(0)
    
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            self.create_table()
            self.get_table_column_headings()
            self.get_users()
    
        def on_press(self, instance):
            columns = self.data_items[instance.index]['range']
            self.user_no_text_input.text = self.data_items[columns[0]]['text']
            self.user_name_text_input.text = self.data_items[columns[1]]['text']
    
        def get_table_column_headings(self):
            connection = sqlite3.connect("demo.db")
    
            with connection:
                # With the with keyword, the Python interpreter automatically releases the resources.
                # It also provides error handling
                cursor = connection.cursor()
                cursor.execute("PRAGMA table_info(Users)")
                col_headings = cursor.fetchall()
                self.total_col_headings = len(col_headings)
        ...
    
        def get_users(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
    
            cursor.execute("SELECT * FROM Users ORDER BY UserID ASC")
            rows = cursor.fetchall()
    
            # create list with db column, db primary key, and db column range
            data = []
            low = 0
            high = self.total_col_headings - 1
    
            for row in rows:
                for col in row:
                    data.append([col, row[0], [low, high]])
                low += self.total_col_headings
                high += self.total_col_headings
    
            # create data_items
            self.data_items = [{'text': str(x[0]), 'Index': str(x[1]), 'range': x[2]} for x in data]
    

    例子

    主.py

    import sqlite3
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.recycleview.views import RecycleDataViewBehavior
    from kivy.uix.button import Button
    from kivy.properties import BooleanProperty, ListProperty, NumericProperty, ObjectProperty
    from kivy.uix.recyclegridlayout import RecycleGridLayout
    from kivy.uix.behaviors import FocusBehavior
    from kivy.uix.recycleview.layout import LayoutSelectionBehavior
    
    
    class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
                                      RecycleGridLayout):
        ''' Adds selection and focus behaviour to the view. '''
    
    
    class SelectableButton(RecycleDataViewBehavior, Button):
        ''' Add selection support to the Button '''
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
    
        def refresh_view_attrs(self, rv, index, data):
            ''' Catch and handle the view changes '''
            self.index = index
            return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
    
        def on_touch_down(self, touch):
            ''' Add selection on touch down '''
            if super(SelectableButton, self).on_touch_down(touch):
                return True
            if self.collide_point(*touch.pos) and self.selectable:
                return self.parent.select_with_touch(self.index, touch)
    
        def apply_selection(self, rv, index, is_selected):
            ''' Respond to the selection of items in the view. '''
            self.selected = is_selected
    
    
    class RV(BoxLayout):
        ''' Creates Db conn, table, and saves data, retrives stored data and
        displays in the RecycleView .'''
        data_items = ListProperty([])
        user_no_text_input = ObjectProperty(None)
        user_name_text_input = ObjectProperty(None)
        total_col_headings = NumericProperty(0)
    
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            self.create_table()
            self.get_table_column_headings()
            self.get_users()
    
        def on_press(self, instance):
            columns = self.data_items[instance.index]['range']
            self.user_no_text_input.text = self.data_items[columns[0]]['text']
            self.user_name_text_input.text = self.data_items[columns[1]]['text']
    
        def get_table_column_headings(self):
            connection = sqlite3.connect("demo.db")
    
            with connection:
                # With the with keyword, the Python interpreter automatically releases the resources.
                # It also provides error handling
                cursor = connection.cursor()
                cursor.execute("PRAGMA table_info(Users)")
                col_headings = cursor.fetchall()
                self.total_col_headings = len(col_headings)
    
        def create_table(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
            sql = """CREATE TABLE IF NOT EXISTS Users(
            UserID integer PRIMAY KEY,
            UserName text NOT NULL)"""
            cursor.execute(sql)
            connection.close()
    
        def get_users(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
    
            cursor.execute("SELECT * FROM Users ORDER BY UserID ASC")
            rows = cursor.fetchall()
    
            # create list with db column, db primary key, and db column range
            data = []
            low = 0
            high = self.total_col_headings - 1
    
            for row in rows:
                for col in row:
                    data.append([col, row[0], [low, high]])
                low += self.total_col_headings
                high += self.total_col_headings
    
            # create data_items
            self.data_items = [{'text': str(x[0]), 'Index': str(x[1]), 'range': x[2]} for x in data]
    
        def save(self):
            connection = sqlite3.connect("demo.db")
            cursor = connection.cursor()
    
            UserID = self.user_no_text_input.text
            UserName = self.user_name_text_input.text
    
            try:
                save_sql = "INSERT INTO Users (UserID, UserName) VALUES (?,?)"
                cursor.execute(save_sql, (UserID, UserName))
                connection.commit()
                connection.close()
            except sqlite3.IntegrityError as e:
                print("Error: ", e)
    
    
    class TestApp(App):
        title = "Kivy RecycleView & SQLite3 Demo"
    
        def build(self):
            return RV()
    
    
    if __name__ == "__main__":
        TestApp().run()
    

    测试.kv

    #:kivy 1.11.0
    
    <SelectableButton>:
        # Draw a background to indicate selection
        canvas.before:
            Color:
                rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
            Rectangle:
                pos: self.pos
                size: self.size
        on_press:
            app.root.on_press(self)
    
    <RV>:
        user_no_text_input: no
        user_name_text_input: name
    
        BoxLayout:
            orientation: "vertical"
    
            Label:
                text: "USER NUMBER"
                size_hint: (.5, None)
                height: 30
            TextInput:
                id: no
                size_hint: (.5, None)
                height: 30
                multiline: False
            Label:
                text: "USER NAME"
                size_hint: (.5, None)
                height: 30
            TextInput:
                id: name
                size_hint: (.5, None)
                height: 30
                multiline: False
            Button:
                id: save_btn
                text: "SAVE BUTTON"
                height: 50
                width: 100
                on_press: root.save()
    
            GridLayout:
                size_hint: 1, None
                size_hint_y: None
                height: 25
                cols: 2
    
                Label:
                    text: "User ID"
                Label:
                    text: "User Name"
    
            BoxLayout:
                RecycleView:
                    viewclass: 'SelectableButton'
                    data: root.data_items
                    SelectableRecycleGridLayout:
                        cols: 2
                        default_size: None, dp(26)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        orientation: 'vertical'
                        multiselect: True
                        touch_multiselect: True
    

    产量

    Img01 Img02