<legend id='TrWXS'><style id='TrWXS'><dir id='TrWXS'><q id='TrWXS'></q></dir></style></legend><tfoot id='TrWXS'></tfoot>

        <small id='TrWXS'></small><noframes id='TrWXS'>

      1. <i id='TrWXS'><tr id='TrWXS'><dt id='TrWXS'><q id='TrWXS'><span id='TrWXS'><b id='TrWXS'><form id='TrWXS'><ins id='TrWXS'></ins><ul id='TrWXS'></ul><sub id='TrWXS'></sub></form><legend id='TrWXS'></legend><bdo id='TrWXS'><pre id='TrWXS'><center id='TrWXS'></center></pre></bdo></b><th id='TrWXS'></th></span></q></dt></tr></i><div id='TrWXS'><tfoot id='TrWXS'></tfoot><dl id='TrWXS'><fieldset id='TrWXS'></fieldset></dl></div>
          <bdo id='TrWXS'></bdo><ul id='TrWXS'></ul>
      2. Python:如何在 RecycleView 中添加垂直滚动

        时间:2023-10-10
          • <bdo id='V7XuN'></bdo><ul id='V7XuN'></ul>

              <legend id='V7XuN'><style id='V7XuN'><dir id='V7XuN'><q id='V7XuN'></q></dir></style></legend>

              <tfoot id='V7XuN'></tfoot>
              <i id='V7XuN'><tr id='V7XuN'><dt id='V7XuN'><q id='V7XuN'><span id='V7XuN'><b id='V7XuN'><form id='V7XuN'><ins id='V7XuN'></ins><ul id='V7XuN'></ul><sub id='V7XuN'></sub></form><legend id='V7XuN'></legend><bdo id='V7XuN'><pre id='V7XuN'><center id='V7XuN'></center></pre></bdo></b><th id='V7XuN'></th></span></q></dt></tr></i><div id='V7XuN'><tfoot id='V7XuN'></tfoot><dl id='V7XuN'><fieldset id='V7XuN'></fieldset></dl></div>

              1. <small id='V7XuN'></small><noframes id='V7XuN'>

                    <tbody id='V7XuN'></tbody>
                  本文介绍了Python:如何在 RecycleView 中添加垂直滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我正在使用 Python-2.7kivy.
                  我运行 test.py 然后显示一个菜单 Test.当我点击它然后显示 list 的数据.谁能告诉我如何在列表中添加垂直 scrollbar.

                  test.py

                  从 kivy.app 导入 App从 kivy.uix.boxlayout 导入 BoxLayout从 kivy.properties 导入 BooleanProperty、ListProperty、ObjectProperty、NumericProperty、DictProperty从 kivy.uix.recycleview.views 导入 RecycleDataViewBehavior从 kivy.uix.button 导入按钮从 kivy.uix.recyclegridlayout 导入 RecycleGridLayout从 kivy.uix.behaviors 导入 FocusBehavior从 kivy.uix.recycleview.layout 导入 LayoutSelectionBehavior从 kivy.uix.popup 导入弹出窗口从 kivy.core.window 导入窗口从 kivy.clock 导入时钟窗口大小 = (600, 325)类 SelectableRecycleGridLayout(FocusBehavior,LayoutSelectionBehavior,回收网格布局):''' 将选择和焦点行为添加到视图.'''selected_row = NumericProperty(0)def get_nodes(self):节点 = self.get_selectable_nodes()如果 self.nodes_order_reversed:节点=节点[::-1]如果不是节点:返回无,无selected = self.selected_nodesif not selected: # 没有选择,选择第一个self.select_node(节点[0])self.selected_row = 0返回无,无if len(nodes) == 1: # 唯一可选择的节点已经被选中返回无,无最后 = 节点索引(选定 [-1])self.clear_selection()最后返回,节点def select_next(self):'''选择下一行'''最后,节点 = self.get_nodes()如果不是节点:返回如果最后 == len(nodes) - 1:self.select_node(节点[0])self.selected_row = 节点[0]别的:self.select_node(nodes[last + 1])self.selected_row = 节点[last + 1]def select_previous(self):''' 选择上一行 '''最后,节点 = self.get_nodes()如果不是节点:返回如果不是最后:self.select_node(节点[-1])self.selected_row = 节点[-1]别的:self.select_node(nodes[last - 1])self.selected_row = 节点[last - 1]def select_current(self):''' 选择当前行 '''最后,节点 = self.get_nodes()如果不是节点:返回self.select_node(节点[self.selected_row])类 SelectableButton(RecycleDataViewBehavior,按钮):''' 为按钮添加选择支持 '''索引 = 无选择 = BooleanProperty(False)可选 = BooleanProperty(True)def refresh_view_attrs(self, rv, index, data):''' 捕捉并处理视图变化 '''self.index = 索引return super(SelectableButton, self).refresh_view_attrs(rv, index, data)def on_touch_down(自我,触摸):'''在触地时添加选择'''if super(SelectableButton, self).on_touch_down(touch):返回真如果 self.collide_point(*touch.pos) 和 self.selectable:打印(on_touch_down:自我=",自我)返回 self.parent.select_with_touch(self.index, touch)def apply_selection(self, rv, index, is_selected):''' 响应视图中项目的选择.'''self.selected = is_selectedRV类(BoxLayout):data_items = ListProperty([])row_data = DictProperty({})col1_data = ListProperty([])col2_data = ListProperty([])col1_row_controller = ObjectProperty(无)col2_row_controller = ObjectProperty(无)def __init__(self, **kwargs):超级(房车,自我).__init__(**kwargs)self.get_states()Clock.schedule_once(self.set_default_first_row, .0005)self._request_keyboard()def _request_keyboard(self):self._keyboard = Window.request_keyboard(self._keyboard_closed,自我,'文本')如果 self._keyboard.widget:# 如果它存在,这个小部件是一个你可以使用的 VKeyboard 对象# 更改键盘布局.经过self._keyboard.bind(on_key_down=self._on_keyboard_down)def _keyboard_closed(self):self._keyboard.unbind(on_key_down=self._on_keyboard_down)self._keyboard = 无def _on_keyboard_down(自我,键盘,键码,文本,修饰符):if keycode[1] == 'down': # keycode[274, 'down'] 按下# 响应键盘向下箭头按下self.display_keystrokes(键盘、键码、文本、修饰符)self.col1_row_controller.select_next()self.col2_row_controller.select_next()elif keycode[1] == 'up': # keycode[273, 'up] 按下# 响应键盘向上箭头按下self.display_keystrokes(键盘、键码、文本、修饰符)self.col1_row_controller.select_previous()self.col2_row_controller.select_previous()# Keycode由整数+字符串组成# 如果我们按下escape,释放键盘如果键码 [1] == '转义':键盘.release()# 返回 True 以接受密钥.否则,它将被# 系统.返回真def display_keystrokes(self, keyboard, keycode, text, modifiers):print("
                  键", keycode, "已被按下")print(" - 文本是 %r" % 文本)print(" - 修饰符是 %r" % 修饰符)def on_keyboard_select(self):''' 响应键盘事件调用 Popup '''# 为 Popup 设置行数据self.row_data = self.col1_data[self.col1_row_controller.selected_row]# 调用弹出窗口self.popup_callback()def on_mouse_select(self, instance):'''响应鼠标事件调用Popup '''if (self.col1_row_controller.selected_row != instance.index或 self.col2_row_controller.selected_row != instance.index):# 鼠标点击的行不等于当前选中的行self.col1_row_controller.selected_row = instance.indexself.col2_row_controller.selected_row = instance.index# 高亮鼠标点击/选中的行self.col1_row_controller.select_current()self.col2_row_controller.select_current()# 为 Popup 设置行数据# 我们可以使用 col1_data 或 col2_data,因为它们是重复的,并且每个都存储相同的信息self.row_data = self.col1_data[instance.index]# 调用弹出窗口self.popup_callback()def popup_callback(self):# 启用键盘请求self._request_keyboard()def set_default_first_row(self, dt):''' 设置默认第一行为选中'''self.col1_row_controller.select_next()self.col2_row_controller.select_next()定义更新(自我):self.col1_data = [{'text': str(x[0]), 'Id': str(x[0]), 'Name': x[1], 'key': 'Id', 'selectable': 真的}对于 self.data_items 中的 x]self.col2_data = [{'text': x[1], 'Id': str(x[0]), 'Name': x[1], 'key': 'Name', 'selectable': True}对于 self.data_items 中的 x]def get_states(self):行 = [(1, 'abc'), (1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc')]我 = 0对于行中的行:self.data_items.append([row[0], row[1], i])我 += 1打印(self.data_items)自我更新()类 MainMenu(BoxLayout):states_cities_or_areas = ObjectProperty(无)rv = 对象属性(无)定义显示状态(自我):self.remove_widgets()self.rv = RV()self.states_cities_or_areas.add_widget(self.rv)def remove_widgets(self):self.states_cities_or_areas.clear_widgets()类测试应用程序(应用程序):标题=测试"定义构建(自我):返回主菜单()如果 __name__ == '__main__':TestApp().run()

                  test.kv

                  #:kivy 1.10.0<可选按钮>:画布之前:颜色:rgba: (0, 0.517, 0.705, 1) if self.selected else (0, 0.517, 0.705, 1)长方形:pos: self.pos尺寸:self.sizebackground_color: [1, 0, 0, 1] if self.selected else [1, 1, 1, 1] #深红色 else深灰色on_press: app.root.rv.on_mouse_select(self)<房车>:col1_row_controller:col1_row_controllercol2_row_controller: col2_row_controller方向:垂直"网格布局:大小提示:1,无size_hint_y:无身高:25列数:3标签:size_hint_x: .1文字:身份证"标签:size_hint_x:0.5文字:姓名"滚动视图:id: kr_scrolldo_scroll_x: 假高度:2盒子布局:回收视图:size_hint_x: .1数据:root.col1_data视图类:可选按钮"可选回收网格布局:id: col1_row_controllerkey_selection: '可选择的'列数:1default_size:无,dp(26)default_size_hint:1,无size_hint_y:无高度:self.minimum_height方向:垂直"多选:真touch_multiselect:真回收视图:size_hint_x:0.5数据:root.col2_data视图类:可选按钮"可选回收网格布局:id: col2_row_controllerkey_selection: '可选择的'列数:1default_size:无,dp(26)default_size_hint:1,无size_hint_y:无高度:self.minimum_height方向:垂直"多选:真touch_multiselect:真<菜单按钮@按钮>:text_size: self.size对齐:中间"padding_x: 5尺寸:(80,30)size_hint:(无,无)背景颜色:90、90、90、90背景正常:''颜色:0、0.517、0.705、1边框:(0, 10, 0, 0)<主菜单>:states_cities_or_areas: states_cities_or_areas盒子布局:方向:垂直"#间距:10盒子布局:画布之前:长方形:pos: self.pos尺寸:self.sizesize_hint_y: 1菜单按钮:编号:btn文字:'测试'尺寸:(60,30)on_release: root.display_states()盒子布局:画布之前:长方形:pos: self.pos尺寸:self.size颜色:RGB:(1,1,1)标签:size_hint_x: 45盒子布局:id: states_cities_or_areassize_hint_y: 10标签:size_hint_y: 1

                  解决方案

                  问题

                  <块引用>

                  如何仅在 customerId 列和其他列中设置文本右对齐应该左对齐吗?

                  解决方案

                  片段

                  def apply_selection(self, rv, index, is_selected):''' 响应视图中项目的选择.'''self.selected = is_selectedself.text_size = self.size如果 index == rv.data[index]['range'][0]:self.halign = '对'别的:self.halign = '左'

                  输出

                  标签 - 文本垂直增长并以特定宽度换行

                  一个可以垂直增长但以一定宽度包裹文本的Label:

                  标签:size_hint_y:无text_size:self.width,无高度:self.texture_size[1]

                  要在 X 轴/水平和 Y 轴/垂直滚动 GridLayout,请将 size_hint 属性设置为 (None, None).

                  ScrollView - ScrollEffect、scroll_type、bar_width 等

                  <块引用>

                  默认情况下,ScrollView 允许沿 X 轴和 Y 轴滚动.您可以通过将 do_scroll_x 或 do_scroll_y 属性设置为 False 来显式禁用轴上的滚动.

                  要在 Y 轴/垂直方向上滚动 GridLayout,请设置孩子的宽度为 ScrollView (size_hint_x=1),并设置size_hint_y 属性为无:

                  当滚动超出 ScrollView 的边界时,它使用 ScrollEffect 来处理过度滚动.

                  滚动类型

                  设置用于滚动视图内容的滚动类型.可用选项有:['content']、['bars']、['bars'、'content']

                  ['bars'] 通过拖动或滑动滑动条来滚动内容.

                  网格布局

                  <块引用>

                  cols_minimum

                  每列的最小宽度字典.字典键是列号,例如0、1、2……

                  cols_minimum 是一个 DictProperty,默认为 {}.

                  片段

                  :行控制器:行控制器bar_width: 10bar_color: 1, 0, 0, 1 # 红色bar_inactive_color: 0, 0, 1, 1 # 蓝色effect_cls: "滚动效果"滚动类型:['条']数据:root.rv_data视图类:可选按钮"可选回收网格布局:id:row_controllerkey_selection: '可选择的'列:root.total_col_headingscols_minimum:root.cols_minimumdefault_size:无,dp(26)default_size_hint:1,无size_hint:无,无高度:self.minimum_height宽度:self.minimum_width方向:垂直"多选:真touch_multiselect:真

                  以下示例演示:

                  1. 在 X 轴上滚动表格标题.
                  2. 支持X轴和Y轴滚动.
                  3. 支持弹窗 Y 轴滚动.
                  4. 适用于数据库表中的任何列.
                  5. 使用 GridLayout 改变列宽cols_minimum.
                  6. 将两个 RecycleView 合二为一,因为不需要为 ID 设置一个 recycleview.
                  7. 可选择的按钮.

                  SQLite 示例数据库

                  chinook SQLite 示例数据库

                  示例

                  main.py

                  从 kivy.app 导入 App从 kivy.uix.boxlayout 导入 BoxLayout从 kivy.properties 导入 BooleanProperty、ListProperty、ObjectProperty、NumericProperty、DictProperty从 kivy.uix.recycleview.views 导入 RecycleDataViewBehavior从 kivy.uix.button 导入按钮从 kivy.uix.recyclegridlayout 导入 RecycleGridLayout从 kivy.uix.behaviors 导入 FocusBehavior从 kivy.uix.recycleview.layout 导入 LayoutSelectionBehavior从 kivy.uix.popup 导入弹出窗口从 kivy.core.window 导入窗口从 kivy.clock 导入时钟从 kivy.uix.scrollview 导入 ScrollView从 kivy.uix.label 导入标签从 kivy.uix.textinput 导入 TextInput从 kivy.uix.recycleview 导入 RecycleView将 sqlite3 导入为 lite重新进口窗口大小 = (600, 325)类 PopupLabelCell(标签):经过类 EditStatePopup(弹出):def __init__(self, obj, **kwargs):super(EditStatePopup, self).__init__(**kwargs)self.populate_content(obj)def populate_content(self, obj):对于 x 在范围内(len(obj.table_header.col_headings)):self.container.add_widget(PopupLabelCell(text=obj.table_header.col_headings[x]))textinput = TextInput(text=str(obj.row_data[x]))如果 x == 0:textinput.readonly = Trueself.container.add_widget(textinput)类 SelectableRecycleGridLayout(FocusBehavior,LayoutSelectionBehavior,回收网格布局):''' 将选择和焦点行为添加到视图.'''selected_row = NumericProperty(0)obj = ObjectProperty(无)def get_nodes(self):节点 = self.get_selectable_nodes()如果 self.nodes_order_reversed:节点=节点[::-1]如果不是节点:返回无,无selected = self.selected_nodesif not selected: # 没有选择,选择第一个self.selected_row = 0self.select_row(节点)返回无,无if len(nodes) == 1: # 唯一可选择的节点已经被选中返回无,无最后 = 节点索引(选定 [-1])self.clear_selection()最后返回,节点def select_next(self, obj):'''选择下一行'''自我.obj = obj最后,节点 = self.get_nodes()如果不是节点:返回如果最后 == len(nodes) - 1:self.selected_row = 节点[0]别的:self.selected_row = 节点[last + 1]self.selected_row += self.obj.total_col_headingsself.select_row(节点)def select_previous(self, obj):''' 选择上一行 '''自我.obj = obj最后,节点 = self.get_nodes()如果不是节点:返回如果不是最后:self.selected_row = 节点[-1]别的:self.selected_row = 节点[last - 1]self.selected_row -= self.obj.total_col_headingsself.select_row(节点)def select_current(self, obj):''' 选择当前行 '''自我.obj = obj最后,节点 = self.get_nodes()如果不是节点:返回self.select_row(节点)def select_row(自我,节点):col = self.obj.rv_data[self.selected_row]['range']对于范围内的 x(col[0],col[1] + 1):self.select_node(节点[x])类 SelectableButton(RecycleDataViewBehavior,按钮):''' 为按钮添加选择支持 '''索引 = 无选择 = BooleanProperty(False)可选 = BooleanProperty(True)def refresh_view_attrs(self, rv, index, data):''' 捕捉并处理视图变化 '''self.index = 索引return super(SelectableButton, self).refresh_view_attrs(rv, index, data)def on_touch_down(自我,触摸):'''在触地时添加选择'''if super(SelectableButton, self).on_touch_down(touch):返回真如果 self.collide_point(*touch.pos) 和 self.selectable:打印(on_touch_down:自我=",自我)返回 self.parent.select_with_touch(self.index, touch)def apply_selection(self, rv, index, is_selected):''' 响应视图中项目的选择.'''self.selected = is_selectedself.text_size = self.size如果 index == rv.data[index]['range'][0]:self.halign = '对'别的:self.halign = '左'类 HeaderCell(标签):经过类表头(滚动视图):"""固定的表头,用数据表滚动 x"""标头 = 对象属性(无)col_headings = ListProperty([])cols_minimum = 字典属性({})def __init__(self, **kwargs):super(TableHeader, self).__init__(**kwargs)self.db = lite.connect('chinook.db')self.db_cursor = self.db.cursor()self.get_table_column_headings()def get_table_column_headings(self):self.db_cursor.execute("PRAGMA table_info(customers)")col_headings = self.db_cursor.fetchall()对于 col_headings 中的 col_heading:data_type = col_heading[2]如果 data_type == 整数":self.cols_minimum[col_heading[0]] = 100别的:self.cols_minimum[col_heading[0]] = int(re.findall(r'd+', data_type).pop(0)) * 5self.col_headings.append(col_heading[1])self.header.add_widget(HeaderCell(text=col_heading[1], width=self.cols_minimum[col_heading[0]]))房车类(回收视图):row_data = ()rv_data = ListProperty([])row_controller = ObjectProperty(无)total_col_headings = NumericProperty(0)cols_minimum = 字典属性({})table_header = ObjectProperty(无)def __init__(self, table_header, **kwargs):超级(房车,自我).__init__(**kwargs)self.table_header = table_headerself.total_col_headings = len(table_header.col_headings)self.cols_minimum = table_header.cols_minimumself.database_connection()self.get_states()Clock.schedule_once(self.set_default_first_row, .0005)self._request_keyboard()def 数据库连接(自我):self.db = lite.connect('chinook.db')self.db_cursor = self.db.cursor()def _request_keyboard(self):self._keyboard = Window.request_keyboard(self._keyboard_closed,自我,'文本')如果 self._keyboard.widget:# 如果它存在,这个小部件是一个你可以使用的 VKeyboard 对象# 更改键盘布局.经过self._keyboard.bind(on_key_down=self._on_keyboard_down)def _keyboard_closed(self):self._keyboard.unbind(on_key_down=self._on_keyboard_down)self._keyboard = 无def _on_keyboard_down(自我,键盘,键码,文本,修饰符):if keycode[1] == 'down': # keycode[274, 'down'] 按下# 响应键盘向下箭头按下self.display_keystrokes(键盘、键码、文本、修饰符)self.row_controller.select_next(self)elif keycode[1] == 'up': # keycode[273, 'up] 按下# 响应键盘向上箭头按下self.display_keystrokes(键盘、键码、文本、修饰符)self.row_controller.select_previous(self)elif len(修饰符)>0 和修饰符[0] == 'ctrl' 和 text == 'e': # ctrl + e 按下# 响应键盘 ctrl + e 按下,并调用 Popupself.display_keystrokes(键盘、键码、文本、修饰符)self.on_keyboard_select()# Keycode由整数+字符串组成# 如果我们按下escape,释放键盘如果键码 [1] == '转义':键盘.release()# 返回 True 以接受密钥.否则,它将被# 系统.返回真def display_keystrokes(self, keyboard, keycode, text, modifiers):print("
                  键", keycode, "已被按下")print(" - 文本是 %r" % 文本)print(" - 修饰符是 %r" % 修饰符)def on_keyboard_select(self):''' 响应键盘事件调用 Popup '''# 为 Popup 设置行数据self.setup_row_data(self.rv_data[self.row_controller.selected_row]['Index'])# 调用弹出窗口self.popup_callback()def on_mouse_select(self, instance):'''响应鼠标事件调用Popup '''如果 self.row_controller.selected_row != instance.index:# 鼠标点击的行不等于当前选中的行self.row_controller.selected_row = instance.index# 高亮鼠标点击/选中的行self.row_controller.select_current(self)# 为 Popup 设置行数据self.setup_row_data(self.rv_data[instance.index]['Index'])# 调用弹出窗口self.popup_callback()# 启用键盘请求self._request_keyboard()def setup_row_data(自我,价值):self.db_cursor.execute("SELECT * FROM customers WHERE CustomerId=?", value)self.row_data = self.db_cursor.fetchone()def popup_callback(self):''' 实例化并打开弹出窗口 '''popup = EditStatePopup(self)popup.open()def set_default_first_row(self, dt):''' 设置默认第一行为选中'''self.row_controller.select_next(self)def get_states(self):self.db_cursor.execute("SELECT * FROM customers ORDER BY CustomerId ASC")行 = self.db_cursor.fetchall()数据 = []低 = 0高 = self.total_col_headings - 1对于行中的行:对于我在范围内(长度(行)):data.append([row[i], row[0], [low, high]])低 += self.total_col_headings高 += self.total_col_headingsself.rv_data = [{'text': str(x[0]), 'Index': str(x[1]), 'range': x[2], 'selectable': True} for x in data]类表(BoxLayout):rv = 对象属性(无)def __init__(self, **kwargs):超级(表,自我).__init__(**kwargs)self.orientation = "垂直"self.header = TableHeader()self.rv = RV(self.header)self.rv.fbind('scroll_x', self.scroll_with_header)self.add_widget(self.header)self.add_widget(self.rv)def scroll_with_header(self, obj, value):self.header.scroll_x = 值类 MainMenu(BoxLayout):states_cities_or_areas = ObjectProperty(无)表 = 对象属性(无)定义显示状态(自我):self.remove_widgets()self.table = 表()self.states_cities_or_areas.add_widget(self.table)def remove_widgets(self):self.states_cities_or_areas.clear_widgets()类测试应用程序(应用程序):标题=测试"定义构建(自我):返回主菜单()如果 __name__ == '__main__':TestApp().run()

                  test.kv

                  #:kivy 1.10.0<弹出标签单元格>size_hint:(无,无)身高:30text_size: self.size对齐:左"对齐:中间"<EditStatePopup>:容器:容器size_hint:无,无尺寸:400、275标题大小:20# title_font: "Verdana"auto_dismiss: 假盒子布局:方向:垂直"滚动视图:bar_width: 10bar_color: 1, 0, 0, 1 # 红色bar_inactive_color: 0, 0, 1, 1 # 蓝色effect_cls: "滚动效果"滚动类型:['条']size_hint:(1,无)网格布局:编号:容器列数:2行默认高度:30cols_minimum: {0: 100, 1: 300}# 间距:10, 10# 填充:20、20size_hint:(无,无)高度:self.minimum_height盒子布局:按钮:大小提示:1, 0.2文本:保存更改"on_release:root.dismiss()按钮:大小提示:1, 0.2文本:取消更改"on_release: root.dismiss()<可选按钮>:画布之前:颜色:rgba: (0, 0.517, 0.705, 1) if self.selected else (0, 0.517, 0.705, 1)长方形:pos: self.pos尺寸:self.sizebackground_color: [1, 0, 0, 1] if self.selected else [1, 1, 1, 1] #深红色 else深灰色on_press:app.root.table.rv.on_mouse_select(self)<标题单元格>size_hint:(无,无)身高:25text_size: self.size对齐:左"对齐:中间"背景_禁用_正常:''disabled_color: (1, 1, 1, 1)画布之前:颜色:RGBA:1、0.502、0、1长方形:pos: self.pos尺寸:self.size<表头>:标头:标头bar_width: 0do_scroll: 假size_hint:(1,无)身高:25effect_cls: "滚动效果"网格布局:id: 标头行数:1cols_minimum:root.cols_minimumsize_hint:(无,无)宽度:self.minimum_width高度:self.minimum_height<房车>:行控制器:行控制器bar_width: 10bar_color: 1, 0, 0, 1 # 红色bar_inactive_color: 0, 0, 1, 1 # 蓝色effect_cls: "滚动效果"滚动类型:['条']数据:root.rv_data视图类:可选按钮"可选回收网格布局:id:row_controllerkey_selection: '可选择的'列:root.total_col_headingscols_minimum:root.cols_minimumdefault_size:无,dp(26)default_size_hint:1,无size_hint:无,无高度:self.minimum_height宽度:self.minimum_width方向:垂直"多选:真touch_multiselect:真<菜单按钮@按钮>:text_size: self.size对齐:中间"padding_x: 5尺寸:(80,30)size_hint:(无,无)背景颜色:90、90、90、90背景正常:''颜色:0、0.517、0.705、1边框:(0, 10, 0, 0)<主菜单>:states_cities_or_areas: states_cities_or_areas盒子布局:方向:垂直"盒子布局:画布之前:长方形:pos: self.pos尺寸:self.sizesize_hint_y: 1菜单按钮:编号:btn文字:'测试'尺寸:(60,30)on_release: root.display_states()盒子布局:画布之前:长方形:pos: self.pos尺寸:self.size颜色:RGB:(1,1,1)标签:size_hint_x: 45盒子布局:id: states_cities_or_areassize_hint_y: 10标签:size_hint_y: 1

                  输出

                  I am using Python-2.7 and kivy.
                  I run test.py then show a menu Test.When i click on it then show list of data. Can someone tell me how to add vertical scrollbar on list.

                  test.py

                  from kivy.app import App
                  from kivy.uix.boxlayout import BoxLayout
                  from kivy.properties import BooleanProperty, ListProperty, ObjectProperty, NumericProperty, DictProperty
                  
                  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
                  from kivy.clock import Clock
                  
                  Window.size = (600, 325)
                  
                  class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
                                                    RecycleGridLayout):
                      ''' Adds selection and focus behaviour to the view. '''
                  
                      selected_row = NumericProperty(0)
                  
                      def get_nodes(self):
                          nodes = self.get_selectable_nodes()
                          if self.nodes_order_reversed:
                              nodes = nodes[::-1]
                          if not nodes:
                              return None, None
                  
                          selected = self.selected_nodes
                          if not selected:    # nothing selected, select the first
                              self.select_node(nodes[0])
                              self.selected_row = 0
                              return None, None
                  
                          if len(nodes) == 1:     # the only selectable node is selected already
                              return None, None
                  
                          last = nodes.index(selected[-1])
                          self.clear_selection()
                          return last, nodes
                  
                      def select_next(self):
                          ''' Select next row '''
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          if last == len(nodes) - 1:
                              self.select_node(nodes[0])
                              self.selected_row = nodes[0]
                          else:
                              self.select_node(nodes[last + 1])
                              self.selected_row = nodes[last + 1]
                  
                      def select_previous(self):
                          ''' Select previous row '''
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          if not last:
                              self.select_node(nodes[-1])
                              self.selected_row = nodes[-1]
                          else:
                              self.select_node(nodes[last - 1])
                              self.selected_row = nodes[last - 1]
                  
                      def select_current(self):
                          ''' Select current row '''
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          self.select_node(nodes[self.selected_row])
                  
                  
                  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:
                              print("on_touch_down: self=", self)
                              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):
                      data_items = ListProperty([])
                      row_data = DictProperty({})
                      col1_data = ListProperty([])
                      col2_data = ListProperty([])
                      col1_row_controller = ObjectProperty(None)
                      col2_row_controller = ObjectProperty(None)
                  
                      def __init__(self, **kwargs):
                          super(RV, self).__init__(**kwargs)
                          self.get_states()
                          Clock.schedule_once(self.set_default_first_row, .0005)
                          self._request_keyboard()
                  
                      def _request_keyboard(self):
                          self._keyboard = Window.request_keyboard(
                              self._keyboard_closed, self, 'text'
                          )
                          if self._keyboard.widget:
                              # If it exists, this widget is a VKeyboard object which you can use
                              # to change the keyboard layout.
                              pass
                          self._keyboard.bind(on_key_down=self._on_keyboard_down)
                  
                      def _keyboard_closed(self):
                          self._keyboard.unbind(on_key_down=self._on_keyboard_down)
                          self._keyboard = None
                  
                      def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
                          if keycode[1] == 'down':    # keycode[274, 'down'] pressed
                              # Respond to keyboard down arrow pressed
                              self.display_keystrokes(keyboard, keycode, text, modifiers)
                              self.col1_row_controller.select_next()
                              self.col2_row_controller.select_next()
                  
                          elif keycode[1] == 'up':    # keycode[273, 'up] pressed
                              # Respond to keyboard up arrow pressed
                              self.display_keystrokes(keyboard, keycode, text, modifiers)
                              self.col1_row_controller.select_previous()
                              self.col2_row_controller.select_previous()
                  
                          # Keycode is composed of an integer + a string
                          # If we hit escape, release the keyboard
                          if keycode[1] == 'escape':
                              keyboard.release()
                  
                          # Return True to accept the key. Otherwise, it will be used by
                          # the system.
                          return True
                  
                      def display_keystrokes(self, keyboard, keycode, text, modifiers):
                          print("
                  The key", keycode, "have been pressed")
                          print(" - text is %r" % text)
                          print(" - modifiers are %r" % modifiers)
                  
                      def on_keyboard_select(self):
                          ''' Respond to keyboard event to call Popup '''
                  
                          # setup row data for Popup
                          self.row_data = self.col1_data[self.col1_row_controller.selected_row]
                  
                          # call Popup
                          self.popup_callback()
                  
                      def on_mouse_select(self, instance):
                          ''' Respond to mouse event to call Popup '''
                  
                          if (self.col1_row_controller.selected_row != instance.index
                                  or self.col2_row_controller.selected_row != instance.index):
                              # Mouse clicked on row is not equal to current selected row
                              self.col1_row_controller.selected_row = instance.index
                              self.col2_row_controller.selected_row = instance.index
                  
                              # Hightlight mouse clicked/selected row
                              self.col1_row_controller.select_current()
                              self.col2_row_controller.select_current()
                  
                          # setup row data for Popup
                          # we can use either col1_data or col2_data because they are duplicate and each stores the same info
                          self.row_data = self.col1_data[instance.index]
                  
                          # call Popup
                          self.popup_callback()
                  
                      def popup_callback(self):
                  
                          # enable keyboard request
                          self._request_keyboard()
                  
                      def set_default_first_row(self, dt):
                          ''' Set default first row as selected '''
                          self.col1_row_controller.select_next()
                          self.col2_row_controller.select_next()
                  
                      def update(self):
                          self.col1_data = [{'text': str(x[0]), 'Id': str(x[0]), 'Name': x[1], 'key': 'Id', 'selectable': True}
                                            for x in self.data_items]
                  
                          self.col2_data = [{'text': x[1], 'Id': str(x[0]), 'Name': x[1], 'key': 'Name', 'selectable': True}
                                            for x in self.data_items]
                  
                      def get_states(self):
                          rows = [(1, 'abc'), (1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc'),(1, 'abc')]
                  
                          i = 0
                          for row in rows:
                              self.data_items.append([row[0], row[1], i])
                              i += 1
                          print(self.data_items)
                          self.update()
                  
                  
                  class MainMenu(BoxLayout):
                      states_cities_or_areas = ObjectProperty(None)
                      rv = ObjectProperty(None)
                  
                      def display_states(self):
                          self.remove_widgets()
                          self.rv = RV()
                          self.states_cities_or_areas.add_widget(self.rv)
                  
                      def remove_widgets(self):
                          self.states_cities_or_areas.clear_widgets()
                  
                  
                  class TestApp(App):
                      title = "test"
                  
                      def build(self):
                          return MainMenu()
                  
                  
                  if __name__ == '__main__':
                      TestApp().run()
                  

                  test.kv

                  #:kivy 1.10.0
                  
                  <SelectableButton>:
                      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
                      background_color: [1, 0, 0, 1]  if self.selected else [1, 1, 1, 1]  # dark red else dark grey
                      on_press: app.root.rv.on_mouse_select(self)
                  
                  
                  <RV>:
                      col1_row_controller: col1_row_controller
                      col2_row_controller: col2_row_controller
                  
                      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"
                  
                  
                      ScrollView:
                          id: kr_scroll
                          do_scroll_x: False
                          height: 2
                          BoxLayout:
                              RecycleView:
                                  size_hint_x: .1
                                  data: root.col1_data
                                  viewclass: 'SelectableButton'
                                  SelectableRecycleGridLayout:
                                      id: col1_row_controller
                                      key_selection: 'selectable'
                                      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
                  
                              RecycleView:
                                  size_hint_x: .5
                                  data: root.col2_data
                                  viewclass: 'SelectableButton'
                                  SelectableRecycleGridLayout:
                                      id: col2_row_controller
                                      key_selection: 'selectable'
                                      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
                  
                  
                  <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_cities_or_areas: states_cities_or_areas
                  
                      BoxLayout:
                          orientation: 'vertical'
                          #spacing : 10
                  
                          BoxLayout:
                              canvas.before:
                                  Rectangle:
                                      pos: self.pos
                                      size: self.size
                  
                              size_hint_y: 1
                  
                              MenuButton:
                                  id: btn
                                  text: 'Test'
                                  size : (60,30)
                                  on_release: root.display_states()
                  
                  
                          BoxLayout:
                              canvas.before:
                                  Rectangle:
                                      pos: self.pos
                                      size: self.size
                  
                                  Color:
                                      rgb: (1,1,1)
                  
                              Label:
                                  size_hint_x: 45
                  
                          BoxLayout:
                              id: states_cities_or_areas
                              size_hint_y: 10
                  
                          Label:
                              size_hint_y: 1
                  

                  解决方案

                  Question

                  How to set text right align in only customerId column and other column should be left align?

                  Solution

                  Snippet

                  def apply_selection(self, rv, index, is_selected):
                      ''' Respond to the selection of items in the view. '''
                      self.selected = is_selected
                      self.text_size = self.size
                      if index == rv.data[index]['range'][0]:
                          self.halign = 'right'
                      else:
                          self.halign = 'left'
                  

                  Output

                  Label - Text grow vertically and wraps at a certain width

                  A Label that can grow vertically but wraps the text at a certain width:

                  Label:
                      size_hint_y: None
                      text_size: self.width, None
                      height: self.texture_size[1]
                  

                  To scroll a GridLayout on it’s X-axis/horizontally and Y-axis/vertically, set size_hint property to (None, None).

                  ScrollView - ScrollEffect, scroll_type, bar_width, etc.

                  By default, the ScrollView allows scrolling along both the X and Y axes. You can explicitly disable scrolling on an axis by setting the do_scroll_x or do_scroll_y properties to False.

                  To scroll a GridLayout on it’s Y-axis/vertically, set the child’s width to that of the ScrollView (size_hint_x=1), and set the size_hint_y property to None:

                  When scrolling would exceed the bounds of the ScrollView, it uses a ScrollEffect to handle the overscroll.

                  scroll_type

                  Sets the type of scrolling to use for the content of the scrollview. Available options are: [‘content’], [‘bars’], [‘bars’, ‘content’]

                  [‘bars’] Content is scrolled by dragging or swiping the scoll bars.

                  Grid Layout

                  cols_minimum

                  Dict of minimum width for each column. The dictionary keys are the column numbers, e.g. 0, 1, 2…

                  cols_minimum is a DictProperty and defaults to {}.

                  Snippets

                  <RV>:
                      row_controller: row_controller
                  
                      bar_width: 10
                      bar_color: 1, 0, 0, 1   # red
                      bar_inactive_color: 0, 0, 1, 1   # blue
                      effect_cls: "ScrollEffect"
                      scroll_type: ['bars']
                  
                      data: root.rv_data
                      viewclass: 'SelectableButton'
                  
                      SelectableRecycleGridLayout:
                          id: row_controller
                          key_selection: 'selectable'
                          cols: root.total_col_headings
                          cols_minimum: root.cols_minimum
                          default_size: None, dp(26)
                          default_size_hint: 1, None
                          size_hint: None, None
                          height: self.minimum_height
                          width: self.minimum_width
                          orientation: 'vertical'
                          multiselect: True
                          touch_multiselect: True
                  

                  The following example demonstrates:

                  1. Scrolling of the table header on the X-axis.
                  2. Support scrolling on the X-axis and Y-axis.
                  3. Support scrolling on the Y-axis in the Popup window.
                  4. Works for any columns in database table.
                  5. Varying column width using GridLayout cols_minimum.
                  6. Combined two RecycleView into one as there is no need to have a recycleview just for the ID.
                  7. Selectable buttons.

                  SQLite Sample Database

                  chinook SQLite sample database

                  Example

                  main.py

                  from kivy.app import App
                  from kivy.uix.boxlayout import BoxLayout
                  from kivy.properties import BooleanProperty, ListProperty, ObjectProperty, NumericProperty, DictProperty
                  
                  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
                  from kivy.clock import Clock
                  from kivy.uix.scrollview import ScrollView
                  from kivy.uix.label import Label
                  from kivy.uix.textinput import TextInput
                  from kivy.uix.recycleview import RecycleView
                  import sqlite3 as lite
                  import re
                  
                  Window.size = (600, 325)
                  
                  
                  class PopupLabelCell(Label):
                      pass
                  
                  
                  class EditStatePopup(Popup):
                  
                      def __init__(self, obj, **kwargs):
                          super(EditStatePopup, self).__init__(**kwargs)
                          self.populate_content(obj)
                  
                      def populate_content(self, obj):
                          for x in range(len(obj.table_header.col_headings)):
                              self.container.add_widget(PopupLabelCell(text=obj.table_header.col_headings[x]))
                              textinput = TextInput(text=str(obj.row_data[x]))
                              if x == 0:
                                  textinput.readonly = True
                              self.container.add_widget(textinput)
                  
                  
                  class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
                                                    RecycleGridLayout):
                      ''' Adds selection and focus behaviour to the view. '''
                  
                      selected_row = NumericProperty(0)
                      obj = ObjectProperty(None)
                  
                      def get_nodes(self):
                          nodes = self.get_selectable_nodes()
                          if self.nodes_order_reversed:
                              nodes = nodes[::-1]
                          if not nodes:
                              return None, None
                  
                          selected = self.selected_nodes
                          if not selected:    # nothing selected, select the first
                              self.selected_row = 0
                              self.select_row(nodes)
                              return None, None
                  
                          if len(nodes) == 1:     # the only selectable node is selected already
                              return None, None
                  
                          last = nodes.index(selected[-1])
                          self.clear_selection()
                          return last, nodes
                  
                      def select_next(self, obj):
                          ''' Select next row '''
                          self.obj = obj
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          if last == len(nodes) - 1:
                              self.selected_row = nodes[0]
                          else:
                              self.selected_row = nodes[last + 1]
                  
                          self.selected_row += self.obj.total_col_headings
                          self.select_row(nodes)
                  
                      def select_previous(self, obj):
                          ''' Select previous row '''
                          self.obj = obj
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          if not last:
                              self.selected_row = nodes[-1]
                          else:
                              self.selected_row = nodes[last - 1]
                  
                          self.selected_row -= self.obj.total_col_headings
                          self.select_row(nodes)
                  
                      def select_current(self, obj):
                          ''' Select current row '''
                          self.obj = obj
                          last, nodes = self.get_nodes()
                          if not nodes:
                              return
                  
                          self.select_row(nodes)
                  
                      def select_row(self, nodes):
                          col = self.obj.rv_data[self.selected_row]['range']
                          for x in range(col[0], col[1] + 1):
                              self.select_node(nodes[x])
                  
                  
                  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:
                              print("on_touch_down: self=", self)
                              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.text_size = self.size
                          if index == rv.data[index]['range'][0]:
                              self.halign = 'right'
                          else:
                              self.halign = 'left'
                  
                  
                  class HeaderCell(Label):
                      pass
                  
                  
                  class TableHeader(ScrollView):
                      """Fixed table header that scrolls x with the data table"""
                      header = ObjectProperty(None)
                      col_headings = ListProperty([])
                      cols_minimum = DictProperty({})
                  
                      def __init__(self, **kwargs):
                          super(TableHeader, self).__init__(**kwargs)
                          self.db = lite.connect('chinook.db')
                          self.db_cursor = self.db.cursor()
                          self.get_table_column_headings()
                  
                      def get_table_column_headings(self):
                          self.db_cursor.execute("PRAGMA table_info(customers)")
                          col_headings = self.db_cursor.fetchall()
                  
                          for col_heading in col_headings:
                              data_type = col_heading[2]
                              if data_type == "INTEGER":
                                  self.cols_minimum[col_heading[0]] = 100
                              else:
                                  self.cols_minimum[col_heading[0]] = int(re.findall(r'd+', data_type).pop(0)) * 5
                              self.col_headings.append(col_heading[1])
                              self.header.add_widget(HeaderCell(text=col_heading[1], width=self.cols_minimum[col_heading[0]]))
                  
                  
                  class RV(RecycleView):
                      row_data = ()
                      rv_data = ListProperty([])
                      row_controller = ObjectProperty(None)
                      total_col_headings = NumericProperty(0)
                      cols_minimum = DictProperty({})
                      table_header = ObjectProperty(None)
                  
                      def __init__(self, table_header, **kwargs):
                          super(RV, self).__init__(**kwargs)
                          self.table_header = table_header
                          self.total_col_headings = len(table_header.col_headings)
                          self.cols_minimum = table_header.cols_minimum
                          self.database_connection()
                          self.get_states()
                          Clock.schedule_once(self.set_default_first_row, .0005)
                          self._request_keyboard()
                  
                      def database_connection(self):
                          self.db = lite.connect('chinook.db')
                          self.db_cursor = self.db.cursor()
                  
                      def _request_keyboard(self):
                          self._keyboard = Window.request_keyboard(
                              self._keyboard_closed, self, 'text'
                          )
                          if self._keyboard.widget:
                              # If it exists, this widget is a VKeyboard object which you can use
                              # to change the keyboard layout.
                              pass
                          self._keyboard.bind(on_key_down=self._on_keyboard_down)
                  
                      def _keyboard_closed(self):
                          self._keyboard.unbind(on_key_down=self._on_keyboard_down)
                          self._keyboard = None
                  
                      def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
                          if keycode[1] == 'down':    # keycode[274, 'down'] pressed
                              # Respond to keyboard down arrow pressed
                              self.display_keystrokes(keyboard, keycode, text, modifiers)
                              self.row_controller.select_next(self)
                  
                          elif keycode[1] == 'up':    # keycode[273, 'up] pressed
                              # Respond to keyboard up arrow pressed
                              self.display_keystrokes(keyboard, keycode, text, modifiers)
                              self.row_controller.select_previous(self)
                  
                          elif len(modifiers) > 0 and modifiers[0] == 'ctrl' and text == 'e':     # ctrl + e pressed
                              # Respond to keyboard ctrl + e pressed, and call Popup
                              self.display_keystrokes(keyboard, keycode, text, modifiers)
                              self.on_keyboard_select()
                  
                          # Keycode is composed of an integer + a string
                          # If we hit escape, release the keyboard
                          if keycode[1] == 'escape':
                              keyboard.release()
                  
                          # Return True to accept the key. Otherwise, it will be used by
                          # the system.
                          return True
                  
                      def display_keystrokes(self, keyboard, keycode, text, modifiers):
                          print("
                  The key", keycode, "have been pressed")
                          print(" - text is %r" % text)
                          print(" - modifiers are %r" % modifiers)
                  
                      def on_keyboard_select(self):
                          ''' Respond to keyboard event to call Popup '''
                  
                          # setup row data for Popup
                          self.setup_row_data(self.rv_data[self.row_controller.selected_row]['Index'])
                  
                          # call Popup
                          self.popup_callback()
                  
                      def on_mouse_select(self, instance):
                          ''' Respond to mouse event to call Popup '''
                  
                          if self.row_controller.selected_row != instance.index:
                              # Mouse clicked on row is not equal to current selected row
                              self.row_controller.selected_row = instance.index
                  
                              # Hightlight mouse clicked/selected row
                              self.row_controller.select_current(self)
                  
                          # setup row data for Popup
                          self.setup_row_data(self.rv_data[instance.index]['Index'])
                  
                          # call Popup
                          self.popup_callback()
                  
                          # enable keyboard request
                          self._request_keyboard()
                  
                      def setup_row_data(self, value):
                          self.db_cursor.execute("SELECT * FROM customers WHERE CustomerId=?", value)
                          self.row_data = self.db_cursor.fetchone()
                  
                      def popup_callback(self):
                          ''' Instantiate and Open Popup '''
                          popup = EditStatePopup(self)
                          popup.open()
                  
                      def set_default_first_row(self, dt):
                          ''' Set default first row as selected '''
                          self.row_controller.select_next(self)
                  
                      def get_states(self):
                          self.db_cursor.execute("SELECT * FROM customers ORDER BY CustomerId ASC")
                          rows = self.db_cursor.fetchall()
                  
                          data = []
                          low = 0
                          high = self.total_col_headings - 1
                          for row in rows:
                              for i in range(len(row)):
                                  data.append([row[i], row[0], [low, high]])
                              low += self.total_col_headings
                              high += self.total_col_headings
                  
                          self.rv_data = [{'text': str(x[0]), 'Index': str(x[1]), 'range': x[2], 'selectable': True} for x in data]
                  
                  
                  class Table(BoxLayout):
                      rv = ObjectProperty(None)
                  
                      def __init__(self, **kwargs):
                          super(Table, self).__init__(**kwargs)
                          self.orientation = "vertical"
                          self.header = TableHeader()
                          self.rv = RV(self.header)
                  
                          self.rv.fbind('scroll_x', self.scroll_with_header)
                  
                          self.add_widget(self.header)
                          self.add_widget(self.rv)
                  
                      def scroll_with_header(self, obj, value):
                          self.header.scroll_x = value
                  
                  
                  class MainMenu(BoxLayout):
                      states_cities_or_areas = ObjectProperty(None)
                      table = ObjectProperty(None)
                  
                      def display_states(self):
                          self.remove_widgets()
                          self.table = Table()
                          self.states_cities_or_areas.add_widget(self.table)
                  
                      def remove_widgets(self):
                          self.states_cities_or_areas.clear_widgets()
                  
                  
                  class TestApp(App):
                      title = "test"
                  
                      def build(self):
                          return MainMenu()
                  
                  
                  if __name__ == '__main__':
                      TestApp().run()
                  

                  test.kv

                  #:kivy 1.10.0
                  
                  <PopupLabelCell>
                      size_hint: (None, None)
                      height: 30
                      text_size: self.size
                      halign: "left"
                      valign: "middle"
                  
                  <EditStatePopup>:
                      container: container
                      size_hint: None, None
                      size: 400, 275
                      title_size: 20
                      # title_font: "Verdana"
                      auto_dismiss: False
                  
                      BoxLayout:
                          orientation: "vertical"
                          ScrollView:
                              bar_width: 10
                              bar_color: 1, 0, 0, 1   # red
                              bar_inactive_color: 0, 0, 1, 1   # blue
                              effect_cls: "ScrollEffect"
                              scroll_type: ['bars']
                              size_hint: (1, None)
                  
                              GridLayout:
                                  id: container
                                  cols: 2
                                  row_default_height: 30
                                  cols_minimum: {0: 100, 1: 300}
                                  # spacing: 10, 10
                                  # padding: 20, 20
                                  size_hint: (None, None)
                                  height: self.minimum_height
                  
                          BoxLayout:
                              Button:
                                  size_hint: 1, 0.2
                                  text: "Save Changes"
                                  on_release:
                                      root.dismiss()
                              Button:
                                  size_hint: 1, 0.2
                                  text: "Cancel Changes"
                                  on_release: root.dismiss()
                  
                  <SelectableButton>:
                      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
                      background_color: [1, 0, 0, 1]  if self.selected else [1, 1, 1, 1]  # dark red else dark grey
                      on_press: app.root.table.rv.on_mouse_select(self)
                  
                  <HeaderCell>
                      size_hint: (None, None)
                      height: 25
                      text_size: self.size
                      halign: "left"
                      valign: "middle"
                      background_disabled_normal: ''
                      disabled_color: (1, 1, 1, 1)
                  
                      canvas.before:
                          Color:
                              rgba: 1, 0.502, 0, 1
                          Rectangle:
                              pos: self.pos
                              size: self.size
                  
                  <TableHeader>:
                      header: header
                      bar_width: 0
                      do_scroll: False
                      size_hint: (1, None)
                      height: 25
                      effect_cls: "ScrollEffect"
                  
                      GridLayout:
                          id: header
                          rows: 1
                          cols_minimum: root.cols_minimum
                          size_hint: (None, None)
                          width: self.minimum_width
                          height: self.minimum_height
                  
                  <RV>:
                      row_controller: row_controller
                  
                      bar_width: 10
                      bar_color: 1, 0, 0, 1   # red
                      bar_inactive_color: 0, 0, 1, 1   # blue
                      effect_cls: "ScrollEffect"
                      scroll_type: ['bars']
                  
                      data: root.rv_data
                      viewclass: 'SelectableButton'
                  
                      SelectableRecycleGridLayout:
                          id: row_controller
                          key_selection: 'selectable'
                          cols: root.total_col_headings
                          cols_minimum: root.cols_minimum
                          default_size: None, dp(26)
                          default_size_hint: 1, None
                          size_hint: None, None
                          height: self.minimum_height
                          width: self.minimum_width
                          orientation: 'vertical'
                          multiselect: True
                          touch_multiselect: True
                  
                  
                  <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_cities_or_areas: states_cities_or_areas
                  
                      BoxLayout:
                          orientation: 'vertical'
                  
                          BoxLayout:
                              canvas.before:
                                  Rectangle:
                                      pos: self.pos
                                      size: self.size
                  
                              size_hint_y: 1
                  
                              MenuButton:
                                  id: btn
                                  text: 'Test'
                                  size : (60,30)
                                  on_release: root.display_states()
                  
                  
                          BoxLayout:
                              canvas.before:
                                  Rectangle:
                                      pos: self.pos
                                      size: self.size
                  
                                  Color:
                                      rgb: (1,1,1)
                  
                              Label:
                                  size_hint_x: 45
                  
                          BoxLayout:
                              id: states_cities_or_areas
                              size_hint_y: 10
                  
                          Label:
                              size_hint_y: 1
                  

                  Output

                  这篇关于Python:如何在 RecycleView 中添加垂直滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:如何在 kivy 中开始/使用 matplotlib 下一篇:如何在运行时更改 Kivy 中小部件的颜色?

                  相关文章

                  最新文章

                  <small id='ohkWI'></small><noframes id='ohkWI'>

                  <legend id='ohkWI'><style id='ohkWI'><dir id='ohkWI'><q id='ohkWI'></q></dir></style></legend>

                      <bdo id='ohkWI'></bdo><ul id='ohkWI'></ul>

                    1. <i id='ohkWI'><tr id='ohkWI'><dt id='ohkWI'><q id='ohkWI'><span id='ohkWI'><b id='ohkWI'><form id='ohkWI'><ins id='ohkWI'></ins><ul id='ohkWI'></ul><sub id='ohkWI'></sub></form><legend id='ohkWI'></legend><bdo id='ohkWI'><pre id='ohkWI'><center id='ohkWI'></center></pre></bdo></b><th id='ohkWI'></th></span></q></dt></tr></i><div id='ohkWI'><tfoot id='ohkWI'></tfoot><dl id='ohkWI'><fieldset id='ohkWI'></fieldset></dl></div>
                    2. <tfoot id='ohkWI'></tfoot>