import kivy
kivy.require('1.9.0') # replace with your current kivy version !
import sqlite3 as lite
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, ObjectProperty,NumericProperty
from kivy.lang import Builder
from kivy.uix.dropdown import DropDown
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from kivy.core.window import Window
Window.size = (900, 500)
MAX_TABLE_COLS = 3
con = lite.connect('demo.db')
con.text_factory = str
cur = con.cursor()
class EditStatePopup(Popup):
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditStatePopup, self).__init__(**kwargs)
self.index = obj.index
self.col_data[0] = obj.rv_data[self.index]["Id"]
self.col_data[1] = obj.rv_data[self.index]["Name"]
self.col_data[2] = obj.rv_data[self.index]["Code"]
def package_changes(self, stateName, stateCode):
self.col_data[1] = stateName
self.col_data[2] = stateCode
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)
rv_data = ObjectProperty(None)
start_point = NumericProperty(0)
def __init__(self, **kwargs):
super(SelectableButton, self).__init__(**kwargs)
Clock.schedule_interval(self.update, .0005)
def update(self, *args):
self.text = self.rv_data[self.index][self.key]
def on_press(self):
popup = EditStatePopup(self)
popup.open()
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
self.rv_data = rv.data
#print("selection changed to {0}".format(rv.data[1]))
class RV(BoxLayout):
data_items = ListProperty([])
col1 = ListProperty()
col2 = ListProperty()
col3 = ListProperty()
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_states()
def update(self):
self.col1 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Id'} for x in self.data_items]
self.col2 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Name'} for x in self.data_items]
self.col3 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Code'} for x in self.data_items]
def get_states(self):
rows = [(1, 'Yash', 'Chopra'), (2, 'amit', 'Kumar')]
# create data_items
i = 0
for row in rows:
self.data_items.append([row[0], row[1], row[2], i])
i += 1
self.update()
class CustDrop(DropDown):
def __init__(self, **kwargs):
super(CustDrop, self).__init__(**kwargs)
self.select('')
class MainMenu(BoxLayout):
rv = ObjectProperty(None)
states = ObjectProperty(None)
dropdown = ObjectProperty(None)
def display_states(self):
self.dropdown.dismiss()
self.remove_widgets()
self.rv = RV()
self.states.add_widget(self.rv)
def remove_widgets(self):
for child in [child for child in self.states.children]:
self.states.remove_widget(child)
def update_states(self, obj):
# update data_items
# obj.start_point + 1 --- skip State_ID
self.rv.data_items[obj.index] = [ obj.col_data[0], obj.col_data[1], obj.col_data[2], obj.index]
self.rv.update()
# update Database Table
cur.execute("UPDATE m_state SET state_name=?, state_code=? WHERE state_id=?",
(obj.col_data[1], obj.col_data[2], obj.col_data[0]))
con.commit()
class TestApp(App):
title = "test"
def build(self):
self.root = Builder.load_file('test.kv')
return MainMenu()
if __name__ == '__main__':
TestApp().run()
#:kivy 1.10.0
#:import CoreImage kivy.core.image.Image
#:import os os
<EditStatePopup>:
title: "Update State"
size_hint: None, None
size: 300, 300
auto_dismiss: False
BoxLayout:
orientation: "vertical"
GridLayout:
cols: 2
Label:
text: "Id"
Label:
id: Id
text: root.col_data[0]
Label:
text: "Name"
TextInput:
id: Name
text: root.col_data[1]
Label:
text: "Code"
TextInput:
id: stateCode
text: root.col_data[2]
Button:
size_hint: 1, 0.4
text: "Cancel"
on_release: root.dismiss()
Button:
size_hint: 1, 0.4
text: "Ok"
on_release:
root.package_changes(Name.text, Code.text)
#root.obj.update_states(root.start_point, root.max_table_cols, root.new_data)
app.root.update_states(root)
root.dismiss()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (0, 0.517, 0.705, 1) if self.selected else (0, 0.517, 0.705, 1)
Rectangle:
pos: self.pos
size: self.size
<MyRV@RecycleView>:
viewclass: 'SelectableButton'
SelectableRecycleGridLayout:
cols: 1
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
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
size_hint_x: .1
text: "Id"
Label:
size_hint_x: .5
text: "Name"
Label:
size_hint_x: .4
text: "Code"
BoxLayout:
MyRV:
size_hint_x: .1
data: root.col1
MyRV:
size_hint_x: .5
data: root.col2
MyRV:
size_hint_x: .4
data: root.col3
<DropdownButton@Button>:
border: (0, 16, 0, 16)
text_size: self.size
valign: "middle"
padding_x: 5
size_hint_y: None
height: '30dp'
#on_release: dropdown.select('')
#on_release: app.root.test
background_color: 90 , 90, 90, 90
color: 0, 0.517, 0.705, 1
#<CustDrop>:
#id: dropdown
#auto_width: False
#width: 150
#DropdownButton:
#text: 'Add State'
#on_release: os.system("python m_State.py")
#DropdownButton:
#text: 'List State'
#on_release: root.display_users()
<MenuButton@Button>:
text_size: self.size
valign: "middle"
padding_x: 5
size : (80,30)
size_hint : (None, None)
background_color: 90 , 90, 90, 90
background_normal: ''
color: 0, 0.517, 0.705, 1
border: (0, 10, 0, 0)
<MainMenu>:
states: states
dropdown: dropdown
BoxLayout:
orientation: 'vertical'
#spacing : 10
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size_hint_y: 1
MenuButton:
id: btn
text: 'Menu'
size : (60,30)
on_release: dropdown.open(self)
CustDrop:
id: dropdown
auto_width: False
width: 150
DropdownButton:
text: 'user'
size_hint_y: None
height: '32dp'
#on_release: dropdown3.open(self)
on_release: root.display_states()
BoxLayout:
id: states
size_hint_y: 9
Label:
size_hint_y: 9
答案 0 :(得分:2)
1.当我点击菜单然后显示子菜单用户。当点击用户然后当我点击任何一行用户时显示用户列表然后显示错误,如附加图像。
您正在迭代行,您只有两行但是有三列
- update_states()函数未在数据库中更新
醇>
我不认为编译器会终止该功能,因为它中的错误很少
要使代码正常工作,我必须进行许多更改
首先在python文件中准备rvs的数据
...
class RV(BoxLayout):
data_items = ListProperty([])
col1 = ListProperty()
col2 = ListProperty()
col3 = ListProperty()
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_states()
def update(self):
self.col1 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Id'} for x in self.data_items]
self.col2 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Name'} for x in self.data_items]
self.col3 = [{'Id': str(x[0]), 'Name': x[1], 'Code': x[2], 'key': 'Code'} for x in self.data_items]
def get_states(self):
#cur.execute("SELECT * FROM `m_state` order by state_id asc")
#rows = cur.fetchall()
rows = [(1, 'Yash', 'Chopra'), (2, 'amit', 'Kumar')]
# create data_items
'''for row in rows:
for col in row:
self.data_items.append(col)'''
i = 0
for row in rows:
self.data_items.append([row[0], row[1], row[2], i])
i += 1
self.update()
...
然后在kv中分别用col1,col2,col3替换rvs的数据
...
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
size_hint_x: .1
text: "Id"
Label:
size_hint_x: .5
text: "Name"
Label:
size_hint_x: .4
text: "Code"
BoxLayout:
MyRV:
size_hint_x: .1
data: root.col1
MyRV:
size_hint_x: .5
data: root.col2
MyRV:
size_hint_x: .4
data: root.col3
...
要在编辑rvs时自动更改rvs按钮的文本,我必须安排一个功能
...
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Button '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
rv_data = ObjectProperty(None)
start_point = NumericProperty(0)
def __init__(self, **kwargs):
super(SelectableButton, self).__init__(**kwargs)
Clock.schedule_interval(self.update, .0005)
def update(self, *args):
self.text = self.rv_data[self.index][self.key]
...
def on_press(self):
popup = EditStatePopup(self)
popup.open()
...
您还要编辑EditStatePopup
,我添加了索引属性,因为在主菜单中与他进行更改会更容易
...
class EditStatePopup(Popup):
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditStatePopup, self).__init__(**kwargs)
self.index = obj.index
self.col_data[0] = obj.rv_data[self.index]["Id"]
self.col_data[1] = obj.rv_data[self.index]["Name"]
self.col_data[2] = obj.rv_data[self.index]["Code"]
最后修改updtate_states
类的MainMenu
:
...
class MainMenu(BoxLayout):
...
def update_states(self, obj):
# update data_items
# obj.start_point + 1 --- skip State_ID
self.rv.data_items[obj.index] = [ obj.col_data[0], obj.col_data[1], obj.col_data[2], obj.index]
self.rv.update()
# update Database Table
cur.execute("UPDATE m_state SET state_name=?, state_code=? WHERE state_id=?",
(obj.col_data[1], obj.col_data[2], obj.col_data[0]))
con.commit()
进行这些更改时请小心。我希望这有帮助