Дочерние объекты TKinter: TypeError: индексы списка должны быть целыми числами или срезами, а не str - PullRequest
1 голос
/ 03 августа 2020

Я немного знаком с 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?

1 Ответ

2 голосов
/ 03 августа 2020

В вашем коде много мелких проблем.

Самая большая проблема, к сожалению, заключается в том, что вы определяете self.children, который конфликтует с внутренним (и, к сожалению, недокументированным) атрибутом то же имя. Вам нужно переименовать свой атрибут во что-нибудь другое. Я не знаю, почему вы храните детей в массиве. Tkinter делает это за вас, поэтому я не думаю, что список self.children вообще необходим.

Следующая проблема заключается в том, что вы не должны звонить self.state так, как вы. Это просто не то, как вы используете self.state.

Метка в DummyChild должна быть дочерним элементом self. Вы пренебрегаете передачей родительского / основного, поэтому по умолчанию он является дочерним по отношению к root.

Вам нужно вызвать pack, place или grid на ярлыке, чтобы он появился в ребенке. Вам также необходимо вызвать один из этих методов в dP, чтобы он отображался в root.

Собирая все вместе, это создает сетку 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...