首页 > 解决方案 > TKinter 子对象:TypeError:列表索引必须是整数或切片,而不是 str

问题描述

我对 python 有一定的经验,对 tkinter 也很陌生。我正在尝试在 2x2 网格中排列四个帧,并且我知道我失败得很惨。我试图创建一个 MWE,甚至失败了,因为它既不工作也不重现我的实际问题,但产生了它自己的一个。但首先,MWE 代码如下:

import tkinter as tk
from tkinter import ttk


class DummyParent(ttk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        master.title('Test')
        self.children = []
        for i in range(4):
            self.children.append(DummyChild(self))
            self.children[i].grid(row=i//2, column=i%2)


class DummyChild(ttk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.state(ttk.Label(text='Test'))


root = tk.Tk()

dP = DummyParent(master=root)
dP.mainloop()

这导致以下堆栈跟踪:

  File "E:/TI/internetofthings/python/tkinter_test.py", line 23, in <module>
    dP = DummyParent(master=root)
  File "E:/TI/internetofthings/python/tkinter_test.py", line 11, in __init__
    self.children.append(DummyChild(self))
  File "E:/TI/internetofthings/python/tkinter_test.py", line 17, in __init__
    super().__init__(master)
  File "C:\Users\Scipio\anaconda3\lib\tkinter\ttk.py", line 742, in __init__
    Widget.__init__(self, master, "ttk::frame", kw)
  File "C:\Users\Scipio\anaconda3\lib\tkinter\ttk.py", line 559, in __init__
    tkinter.Widget.__init__(self, master, widgetname, kw=kw)
  File "C:\Users\Scipio\anaconda3\lib\tkinter\__init__.py", line 2292, in __init__
    BaseWidget._setup(self, master, cnf)
  File "C:\Users\Scipio\anaconda3\lib\tkinter\__init__.py", line 2285, in _setup
    self.master.children[self._name] = self
TypeError: list indices must be integers or slices, not str

self._name发生错误时的值为!dummyparent。真正让我感到困惑的是,我的原始代码在这一点上运行得非常好,即使它与添加的一些实际功能几乎相同。在同一行库代码中,值self._name!firefightermonitor等效的类名称(小写,带有前导感叹号,就像 MWE 一样)。那么,知道我在这里缺少什么吗?还是我只是错误地使用了 tkinter?

标签: pythonpython-3.xtkinter

解决方案


您的代码中有很多小问题。

不幸的是,最大的问题是您正在定义self.children哪个与同名的内部(不幸的是,未记录的)属性发生冲突。您需要将属性重命名为其他名称。我不知道你为什么要把孩子们放在一个数组里。Tkinter 会为您执行此操作,因此我认为该self.children列表根本没有必要。

下一个问题是你不应该像现在这样打电话self.state。这根本不是你使用的方式self.state

中的标签DummyChild必须是self. 您忽略了传递父/主,因此它默认为根的子级。

您需要在标签上调用或pack,以便它出现在子项中。您还需要调用其中一种方法,以便它出现在根目录中。placegriddP

将它们放在一起,这将创建一个 2x2 网格,您的标签可见:

import tkinter as tk
from tkinter import ttk


class DummyParent(ttk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        master.title('Test')
        for row in range(0,2):
            for column in range(0,2):
                child = DummyChild(self)
                child.grid(row=row, column=column, sticky="nsew")


class DummyChild(ttk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.label = ttk.Label(self, text='Test')
        self.label.pack()

root = tk.Tk()

dP = DummyParent(master=root)
dP.pack()
dP.mainloop()

推荐阅读