本文介绍了当我单击行时,它显示错误IndexError:列表索引超出范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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, StringProperty, 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
import sys
#Window.borderless = True

#Window.clearcolor = (0, 0.517, 0.705, 1)

Window.size = (900, 500)
#from easygui import msgbox

#db =lite.connect(':memory:')
con = lite.connect('test.db')
con.text_factory = str
cur = con.cursor()


class EditStatePopup(Popup):
    obj = ObjectProperty(None)
    start_point = NumericProperty(0)
    max_table_cols = NumericProperty(0)
    new_data = ListProperty([])
    stateId = StringProperty("")
    stateName = StringProperty("")
    stateCode = StringProperty("")

    def __init__(self, obj, **kwargs):
        super(EditStatePopup, self).__init__(**kwargs)
        self.obj = obj
        self.start_point = obj.start_point
        self.max_table_cols = obj.max_table_cols
        self.stateId = obj.rv_data[obj.start_point]["text"]
        self.stateName = obj.rv_data[obj.start_point + 1]["text"]
        self.stateCode = obj.rv_data[obj.start_point + 2]["text"]

    def package_changes(self, stateId, stateName, stateCode):
        print(stateName)
        self.new_data.append(stateId)
        self.new_data.append(stateName)
        self.new_data.append(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)
    max_table_cols = NumericProperty(3)
    data_items = ListProperty([])

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


    def on_press(self):
        end_point = self.max_table_cols
        rows = len(self.rv_data) # self.max_table_cols
        #print(end_point) // 3
        #print(rows) // 3
        for row in range(rows):
            cols = list(range(end_point))
            #print(cols) // [0, 1, 2]
            #print(self.index) //1
            #print(self.max_table_cols)//3
            if self.index in cols:
                break
            self.start_point += self.max_table_cols
            end_point += self.max_table_cols

        popup = EditStatePopup(self)
        popup.open()

    def update_states(self, stateId, stateName, stateCode):

        cur.execute("UPDATE m_state SET state_name=?, state_code=? WHERE state_id=?",(stateName, stateCode, stateId))
        con.commit()

class RV(BoxLayout):
    data_items = ListProperty([])

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.get_states()

    def get_states(self):

        cur.execute("SELECT * FROM `m_state` order by state_id asc")
        rows = cur.fetchall()

        #print(rows)
        # create data_items
        rows = [(1, 'Test', '01'), (2, 'test2', '02'), (2, 'test2', '03')]
        for row in rows:
            for col in row:
                self.data_items.append(col)
                #print(col)

class CustDrop(DropDown):
    def __init__(self, **kwargs):
        super(CustDrop, self).__init__(**kwargs)
        self.select('')

class MainMenu(BoxLayout):
    states = ObjectProperty(None)
    dropdown = ObjectProperty(None)

    def display_states(self):
        # rv = RV()
        self.dropdown.dismiss()
        self.states.add_widget(RV())
        #return CustDrop()

class FactApp(App):
    title = "Test"

    def build(self):
        self.root = Builder.load_file('m_ListState.kv')
        return MainMenu()



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

m_ListState.kv

#: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: stateId
                text: root.stateId
            Label:
                text: "Name"
            TextInput:
                id: stateName
                text: root.stateName
            Label:
                text: "Code"
            TextInput:
                id: stateCode
                text: root.stateCode

            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(stateId.text, stateName.text, stateCode.text)
                    #root.obj.update_states(root.start_point, root.max_table_cols, root.new_data)
                    root.obj.update_states(stateId.text, stateName.text, stateCode.text)
                    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"

        GridLayout:
            size_hint: 1, None
            size_hint_y: None
            height: 25
            cols: 3

            Label:
                text: "Id"
            Label:
                text: "Name"
            Label:
                text: "Code"

        BoxLayout:
            RecycleView:
                viewclass: 'SelectableButton'
                data: [{'text': str(x)} for x in root.data_items]
                SelectableRecycleGridLayout:
                    cols: 3
                    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



<DropdownButton@Button>:
    border: (0, 16, 0, 16)
    text_size: self.size
    valign: "middle"
    padding_x: 5
    size_hint_y: None
    height: '30dp'
    background_color: 90 , 90, 90, 90
    color: 0, 0.517, 0.705, 1



<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: 'View'
                size : (60,30)
                on_release: dropdown.open(self)

            CustDrop:
                id: dropdown
                auto_width: False
                width: 150

                DropdownButton:
                    text: 'State'
                    size_hint_y: None
                    height: '32dp'
                    #on_release: dropdown3.open(self)
                    on_release: root.display_states()

                DropdownButton:
                    text: 'City'
                    size_hint_y: None
                    height: '32dp'
                    #on_release: dropdown3.open(self)
                    on_release: root.display_city()

        BoxLayout:
            canvas.before:
                Rectangle:
                    pos: self.pos
                    size: self.size

                Color:
                    rgb: (1,1,1)

            AsyncImage:
                source: "add.jpg"
                #on_release: os.system("python m_State.py")

            Label:
                size_hint_x: 22

        BoxLayout:
            id: states
            size_hint_y: 9

        Label:
            size_hint_y: 9

任何人都可以帮助解决某些问题吗?
1.当我一次又一次点击州(视图的子菜单)然后重复数据.如何避免它.当我点击州时,应该显示州列表,当我点击城市时,应该显示城市列表.display_city( )我还没有写这个仅作为示例.
2.当我单击取消"两次时,它显示错误IndexError:列表索引超出范围.
3.当我更新状态时,它会在数据库中更新,但不会在屏幕上实时更改.如果我再次运行,则会显示更新的数据.

Can anyone help for resolve some issue??
1. when i click on state (submenu of view) again and again then data repeats.How to avoid it.When i click on state then state list should be show and when i click on city then city list should be show.display_city() i have not written yet this for only example.
2. When i click on cancel two times then it shows error IndexError: list index out of range.
3.When i update state then it updated in database but does not change real time on screen.If i again run then shows updated data.

推荐答案

请参阅问题,解决方案和示例以解决您的问题.

Please refer to the problems, solutions and example to solve your problems.

每次单击视图时,都会动态添加窗口小部件.如果单击两次查看",则列将重复两次.

Each time you clicked View, widgets are dynamically added. If you clicked View twice, the columns are repeated twice.

您必须每次都删除小部件,然后才能动态添加它们.

You have to remove the widgets each time before adding them dynamically.

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)

IndexError

问题

每当单击数据的每一行时,它都会调用on_press方法.在实例化SelectableButton类时,将在开始时对self.start_point进行初始化.

IndexError

Problem

Whenever you clicked on each row of data, it invokes the on_press method. The self.start_point is initialized at the beginning when the class SelectableButton is instantiated.

通过on_press方法初始化self.start_point.

Initialize self.start_point in the on_press method.

def on_press(self):
    self.start_point = 0
    end_point = MAX_TABLE_COLS
    rows = len(self.rv_data) // MAX_TABLE_COLS

    for row in range(rows):
        if self.index in list(range(end_point)):
            break
        self.start_point += MAX_TABLE_COLS
        end_point += MAX_TABLE_COLS

    popup = EditStatePopup(self)
    popup.open()

RecycleView未更新

问题

在方法update_states中,缺少RecycleView的数据更新.

RecycleView Not Updated

Problem

In the method update_states, RecycleView's data update is missing.

添加以下内容以更新RecycleView的数据.

Add the following to update RecycleView's data.

def update_states(self, obj):
    # update data_items
    # obj.start_point + 1 --- skip State_ID
    for index in range(obj.start_point + 1, obj.start_point + MAX_TABLE_COLS):
        self.rv.data_items[index] = obj.col_data[index - obj.start_point]

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

示例

m_ListState.py

import kivy
kivy.require('1.10.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

import sys
#Window.borderless = True

#Window.clearcolor = (0, 0.517, 0.705, 1)

Window.size = (900, 500)
#from easygui import msgbox

MAX_TABLE_COLS = 3

path = "/home/iam/dev/SQLite/sampleDB/StateCodesNamesDB/"

#db =lite.connect(':memory:')
# con = lite.connect('fact.db')
con = lite.connect(path + 'country.db')
con.text_factory = str
cur = con.cursor()


class EditStatePopup(Popup):
    start_point = NumericProperty(0)
    col_data = ListProperty(["?", "?", "?"])

    def __init__(self, obj, **kwargs):
        super(EditStatePopup, self).__init__(**kwargs)
        self.start_point = obj.start_point
        self.col_data[0] = obj.rv_data[obj.start_point]["text"]
        self.col_data[1] = obj.rv_data[obj.start_point + 1]["text"]
        self.col_data[2] = obj.rv_data[obj.start_point + 2]["text"]

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

    def on_press(self):
        self.start_point = 0
        end_point = MAX_TABLE_COLS
        rows = len(self.rv_data) // MAX_TABLE_COLS

        for row in range(rows):
            if self.index in list(range(end_point)):
                break
            self.start_point += MAX_TABLE_COLS
            end_point += MAX_TABLE_COLS

        popup = EditStatePopup(self)
        popup.open()


class RV(BoxLayout):
    data_items = ListProperty([])

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.get_states()

    def get_states(self):
        cur.execute("SELECT * FROM m_state order by State_ID asc")
        rows = cur.fetchall()

        # create data_items
        for row in rows:
            for col in row:
                self.data_items.append(col)


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
        for index in range(obj.start_point + 1, obj.start_point + MAX_TABLE_COLS):
            self.rv.data_items[index] = obj.col_data[index - obj.start_point]

        # 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 FactApp(App):
    title = "Test"

    def build(self):
        self.root = Builder.load_file('m_ListState.kv')
        return MainMenu()


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

m_ListState.kv

#: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: stateId
                text: root.col_data[0]
            Label:
                text: "Name"
            TextInput:
                id: stateName
                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(stateName.text, stateCode.text)
                    app.root.update_states(root)
                    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"

        GridLayout:
            size_hint: 1, None
            size_hint_y: None
            height: 25
            cols: 3

            Label:
                text: "Id"
            Label:
                text: "Name"
            Label:
                text: "Code"

        BoxLayout:
            RecycleView:
                viewclass: 'SelectableButton'
                data: [{'text': str(x)} for x in root.data_items]
                SelectableRecycleGridLayout:
                    cols: 3
                    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



<DropdownButton@Button>:
    border: (0, 16, 0, 16)
    text_size: self.size
    valign: "middle"
    padding_x: 5
    size_hint_y: None
    height: '30dp'
    background_color: 90 , 90, 90, 90
    color: 0, 0.517, 0.705, 1



<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: 'View'
                size : (60,30)
                on_release: dropdown.open(self)

            CustDrop:
                id: dropdown
                auto_width: False
                width: 150

                DropdownButton:
                    text: 'State'
                    size_hint_y: None
                    height: '32dp'
                    #on_release: dropdown3.open(self)
                    on_release: root.display_states()

                DropdownButton:
                    text: 'City'
                    size_hint_y: None
                    height: '32dp'
                    #on_release: dropdown3.open(self)
                    on_release: root.display_city()

        BoxLayout:
            canvas.before:
                Rectangle:
                    pos: self.pos
                    size: self.size

                Color:
                    rgb: (1,1,1)

            AsyncImage:
                source: "clipboard.jpeg"    # "gst_image/add.jpg"
                #on_release: os.system("python m_State.py")

            Label:
                size_hint_x: 22

        BoxLayout:
            id: states
            size_hint_y: 9

        Label:
            size_hint_y: 9

输出

Output

这篇关于当我单击行时,它显示错误IndexError:列表索引超出范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-18 18:57