Как я могу изменить текст каждой кнопки во вложенном списке? - PullRequest
1 голос
/ 09 мая 2019

Я осмотрел SO и попробовал предложенные решения, но я не могу изменить text любого button, который я сделал, используя двойную петлю for.

Циклы есть, поэтому я могу добавить их к list из lists из buttons, чтобы я мог (предположительно) получить к ним удобный доступ через вложенный список, вызвав board_button[2][3] или что-то еще.Они также динамически создаются после того, как пользователь вводит board_size, так что он генерирует сетку из кнопок nxn, так что это так.Все это делается внутри метода класса, и есть еще один метод класса, который должен изменить button 'text, когда он вызывается кнопкой.

Я пытался использовать предлагаемые решения здесь , но на самом деле ни одно из них не помогло моей проблеме.

Прошу прощения за длинный блок кода, но я, честно говоря, думаю, способ, которым я его сделал, мог способствовать проблеме и дать более глубокое понимание в результате.

from tkinter import filedialog
from tkinter import *

class MainWindow(Frame):

    board_size = None
    file_input = None
    board_buttons = None
    board_strvars = None

    row = []

    def __init__ (self, parent):
        Frame.__init__(self, parent)

        # initialize widgets but don't show them yet
        self.initWidgets()
        # show the starting window
        self.startWindow()

    def generateBoard(self, to_forget=None):
        # hides the groups of the method that called it
        if to_forget != None:
            for i in to_forget:
                self.row[i].forget()

        # get the board_size from user
        self.board_size = int(self.size_entry.get())

        # initialize text variables for each button
        self.board_strvars = []
        for i in range(self.board_size):
            self.row_strvars=[]
            for j in range(self.board_size):
                var = StringVar()
                var.set("   ")
                self.row_strvars.append(var)

            self.board_strvars.append(self.row_strvars)

        # insert list of lists of buttons here
        self.row[1].pack(fill=X)

        self.board_buttons = []
        for i in range(self.board_size):
            self.row_buttons=[]
            for j in range(self.board_size):
                self.row_buttons.append(Button(self.row[1], textvariable=self.board_strvars[i][j], command=lambda:self.place(i, j)))
                self.row_buttons[j].grid(row=i, column=j)

            self.board_buttons.append(self.row_buttons)

        # for solve and back button
        self.row[2].pack(fill=X)

    def initWidgets(self):
        # create the rows or groups of widgets
        for i in range(3):
            self.row.append(Frame())

        # row 0; startWindow
        self.size_entry = Entry(self.row[0])
        self.size_entry.pack(fill=X, side=LEFT)

        self.size_button = Button(self.row[0], text="Enter", command=lambda:self.generateBoard([0]))
        self.size_button.pack(fill=X, side=LEFT)

        self.load_button = Button(self.row[0], text="Load", command=self.loadFile)
        self.load_button.pack(fill=X, side=LEFT)


        # row 2; generateBoard
        self.solve_button = Button(self.row[2], text="Solve", command=self.showSolutions)
        self.solve_button.pack(fill=X, side=LEFT)

        self.back_button = Button(self.row[2], text="Back", command=lambda:self.startWindow(to_forget=[0,2], to_destroy=[1]))
        self.back_button.pack(fill=X, side=RIGHT)

    def loadFile(self):
        print("file loaded!")

    def place(self, i, j):
        if self.board_strvars[i][j].get() == "   ":
            self.board_strvars[i][j].set("C")
        else:
            self.board_strvars[i][j].set("   ")

    def showSolutions(self):
        print("solutions shown!")


    def startWindow(self, to_forget=None, to_destroy=None):
        # hides the groups of the method that called it
        if to_forget != None:
            for i in to_forget:
                self.row[i].forget()

        # destroys the groups' child widgets and hides the group
        if to_destroy != None:
            for i in to_destroy:
                for child in self.row[i].winfo_children():
                    child.destroy()
                self.row[i].forget()

        self.row[0].pack(fill=X)

if __name__ == "__main__":
    root=Tk()
    root.title("test")
    app = MainWindow(root)
    root.mainloop()

Я изначально хотелопределить функцию, которая изменит text из button, который ее вызвал.Но до сих пор я не нашел способа сделать это.

Использование решений, предложенных в посте, который я связал, ничего не меняет в кнопках.Однако в приведенном мною коде я использовал StringVar(), который был назначен как textvariable из button.Однако он изменяет только последний ряд, последний элемент кнопки столбца, независимо от того, какую кнопку вы нажимаете.Он должен работать так, чтобы кнопка, которая была нажата, изменила свой текст.

Спасибо!

1 Ответ

1 голос
/ 09 мая 2019

Измените функцию lambda, чтобы принудительно закрыть:

def generateBoard(self, to_forget=None):
    ...

    for i in range(self.board_size):
        self.row_buttons=[]
        for j in range(self.board_size):
            self.row_buttons.append(Button(self.row[1], textvariable=self.board_strvars[i][j], command=lambda i=i, j=j:self.place(i, j)))
            self.row_buttons[j].grid(row=i, column=j)

        self.board_buttons.append(self.row_buttons)

Также обратите внимание, что лучше не вызывать собственный метод place, поскольку в Tk уже есть метод place.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...