Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
以编程方式添加和删除tkinter python标签会导致Indexer:list索引超出范围_Python_Python 2.7_Tkinter_Ttk - Fatal编程技术网

以编程方式添加和删除tkinter python标签会导致Indexer:list索引超出范围

以编程方式添加和删除tkinter python标签会导致Indexer:list索引超出范围,python,python-2.7,tkinter,ttk,Python,Python 2.7,Tkinter,Ttk,很抱歉标题含糊不清,但我不知道如何更好地解释自己。基本上,我在tkinter中尝试做的是添加和删除标签。标签值得到更新,因此即使我在开始时删除了一个标签,我的增量始终为1。如果我生成标签并从下往上删除它们,我没有问题,但如果我从中间删除一个标签,然后尝试清理我的列表,我会得到一个错误: Exception in Tkinter callback Traceback (most recent call last): File "/opt/local/Library/Frameworks/Pyt

很抱歉标题含糊不清,但我不知道如何更好地解释自己。基本上,我在tkinter中尝试做的是添加和删除标签。标签值得到更新,因此即使我在开始时删除了一个标签,我的增量始终为1。如果我生成标签并从下往上删除它们,我没有问题,但如果我从中间删除一个标签,然后尝试清理我的列表,我会得到一个错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1536, in __call__
    return self.func(*args)
  File "/Users/XXXX/Helper/development/dynamicListLabels.py", line 21, in <lambda>
    labelList[index].append(ttk.Button(root, text="Remove", command=lambda: removeLabel(labelList[index][0], index)))
IndexError: list index out of range
我的GUI如下所示:

#!/usr/bin/python
from Tkinter import *
import ttk


def removeLabel(labelToRemove, bla):
    labelList[labelToRemove.get()][1].destroy()
    labelList[labelToRemove.get()][2].destroy()
    del labelList[labelToRemove.get()]
    for label in labelList:
        index = labelList.index(label)
        label[0].set(index)


def addNewLabel():
    labelList.append([IntVar()])
    index = len(labelList) - 1
    labelList[index][0].set(index)
    labelList[index].append(ttk.Label(root, textvariable=labelList[index][0]))
    labelList[index].append(ttk.Button(root, text="Remove", command=lambda: removeLabel(labelList[index][0], index)))
    labelList[index][1].grid(column=0)
    labelList[index][2].grid(column=1, row=labelList[index][1].grid_info()['row'])


root = Tk()
labelList = []
ttk.Button(root, text="add label", command=addNewLabel).grid(column=1, row=0)
root.mainloop()

谢谢你的帮助

设计
  • 主要的问题是在处理不同的索引时。试图小心地操作它们会导致复杂的操作,导致代码冗长且效率低下。为了解决这个问题,我们只需去掉它们,并利用您已经在使用的label类变量
    Tkinter.IntVar()
    。这使我们能够完全控制标签和相关的小部件

  • 另一个有效的决策是将每个(标签、按钮)耦合的小部件附加到一个唯一的
    Tkinter.Frame()
    实例上,这样可以避免麻烦。这提供了使用方法删除框架的优势,该方法会自动销毁框架中包含的小部件。同时,这保持了GUI的外观,并使您的应用程序更加灵活,因为它为您提供了添加更多小部件的可能性

  • 设计
    addNewLabel()

    与您的原始代码相比,这里没有什么新的东西,除了,正如我在2中所说的。每个(标签、按钮)耦合将被绘制到一个唯一的
    Tkinter.Frame()
    实例中。当然,在这个方法中,列表框架必须声明为全局的

    设计
    移除标签()

    从1。我们需要传递给
    removeLabel()
    的唯一参数是我们想要去除的标签固有的Tkinter变量(
    var

    然后,我们需要使用在帧列表上循环(
    frames
    ,在下面的代码中),以查找包含我们正在查找的文本变量的标签

    请注意,我在各个帧中的按钮之前绘制标签,
    winfo_children()
    将标签作为第一个小部件列表元素返回

    winfo_children()

    返回一个列表,其中包含窗口所有子级的路径名。顶级窗口作为其逻辑窗口的子窗口返回 父母列表按堆叠顺序排列,首先是最低的窗口, 顶层窗口除外,这些窗口不按堆叠顺序返回。 使用wm stackorder命令查询顶层的堆叠顺序 窗户

    这就是为什么写入:
    if frame.winfo_children()[0].var==var
    并销毁包含满足此条件的标签的框架是正确的

    解决方案 这是节目单。我评论了我认为值得评论的几行:

    '''
    Created on Jun 25, 2016
    
    @author: billal begueradj
    '''
    
    from Tkinter import *
    import ttk
    
    
    def removeLabel(var):
        global frames
        z = -1
        # Loop over the list of rames
        for frame in frames:
            z = z + 1
            # Check the text variable of the label of this frame
            if frame.winfo_children()[0].var == var:
               # Destroy the related frame
               frame.destroy()
               # Update the size of the list of frames
               frames = frames[:z] + frames[z+1:]
               # Do not forget to always rest this flag back to -1
               z = -1 
    
        # Update the labels' numbers       
        r = 0
        for frame in frames:
            frame.winfo_children()[0].var.set(r)
            r = r + 1
    
    
    def addNewLabel():
        global  frames, i
        var = IntVar()
        frame = Frame(root)
        i = i + 1
        frame.grid(row=i, column=0)    
        var.set(len(frames))
        l = ttk.Label(frame, textvariable=var)
        l.grid(row=0, column=0)
        l.var = var
        b = ttk.Button(frame, text="Remove", command=lambda: removeLabel(var))    
        b.grid(row=0, column=1)
        frames.append(frame)
    
    
    if __name__ == '__main__':
       root = Tk()
       frames = []
       i = 1
       ttk.Button(root, text="add label", command=addNewLabel).grid(column=0, row=0)
       root.mainloop()
    
    演示 让我们创建6个标签:

    现在让我们删除标签编号3。您可以看到标签的编号会自动更新:

    现在让我们添加一个新标签。您可以看到新添加的标签具有一个与列表中最后一个现有标签编号连续的编号:


    请注意,列表的长度会根据您的需要随时更新。

    只是一个提示,现在它不会更新标签号,如果您添加或删除两次,您将得到多个相同编号的标签。是的,这不会减少列表大小并更新标签的IntVar()。是的,您是对的,这一次,我仅仅依靠Tkinter变量的内容来避免混乱@LafexlosWOW感谢这个惊人的解释。我仍然试图完全理解一切,但嘿,我在这里学习。非常感谢您的时间Billal BEGUERADJ和@Lafexlos!顺便说一句,我不知道你可以用你的方式(l.var=var)将一个变量/属性添加到一个小部件中。这真方便!