Как создать неизвестное количество объектов TKinter в цикле for - PullRequest
0 голосов
/ 29 октября 2019

У меня есть рамка прокрутки в TKinter. и список кортежей, которые я взял из своей базы данных (управляемой SQlite) для каждого кортежа в списке, я хочу создать строку виджетов в кадре прокрутки, используя цикл for. строка содержит номер строки, флажок, заголовок, взятый из кортежа, и кнопку, которая открывает ссылку, взятую из кортежа. у меня проблема в том, что я не знаю, как создать неизвестное количество строк виджетов в TKinter, а также иметь возможность ссылаться на них. приведенный ниже код работает в том смысле, что он создает строки и т. д., но после их создания я не могу ссылаться на отдельные виджеты. это важно, потому что флажок при клике должен обновить столбец IsActive в моей базе данных (помощь с этим также будет приветствоваться). Я попытался использовать словарь для хранения StringVar () для флажков, но я уверен, что сделал это неправильно.

сам класс является фреймом в окне TKinter. Я ценю, что это может быть глупый вопрос. Я новичок

class details(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="details", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.place(relx=0.5, rely=0.95, anchor = tk.CENTER)

        myframe= tk.Frame(self,relief=tk.GROOVE,bd=1)
        myframe.place(relx=0.5, rely=0.45, anchor = tk.CENTER, width = 750, height = 450)

        self.canvas=tk.Canvas(myframe)
        self.frame=tk.Frame(self.canvas)
        myscrollbar=tk.Scrollbar(myframe,orient="vertical",command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=myscrollbar.set)

        myscrollbar.pack(side="right",fill="y")
        self.canvas.pack(side="left", fill="both")
        self.canvas.create_window((0,0),window=self.frame,anchor='nw')
        self.frame.bind("<Configure>",self.myfunction)
        self.data()

    def data(self):
        lock.acquire(True)
        c.execute("select * from story")
        lock.release()
        results = c.fetchall()
        print(results)
        i = 0
        checkbuttons = {}
## the for loop where rows are created.
        for item in results:

            checkbuttons[item[0]] = tk.IntVar()
            b = item[4]
            s = tk.StringVar()
            tk.Label(self.frame,text=i).grid(row=i,column=0)
            tk.Checkbutton(self.frame, text="", variable=checkbuttons[item[0]], onvalue=1, offvalue=0).grid(row=i,column=1)

            tk.Label(self.frame,textvariable=s, width = 90).grid(row=i,column=2, sticky=tk.W)
            tk.Button(self.frame,text="LINK", command=lambda a = b: self.open_link(a)).grid(row=i,column=3)
            s.set(str(item[3]))
            i+=1
    def myfunction(self, event):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"),width=750,height=500)

    def open_link(self, link):
        print(link)
        webbrowser.open(link, new=1)

1 Ответ

0 голосов
/ 29 октября 2019

проблема в том, что я не знаю, как создать неизвестное количество строк виджетов в TKinter, а также иметь возможность ссылаться на них.

Самое простое решение - этопоместить их в список или словарь, или, в вашем случае, список словарей, где каждая строка в списке представляет собой словарь с данными, которые вы хотите запомнить.

Итак, начните с данных, которые вы хотитеПомните. В вашем случае я предполагаю, что мы хотим иметь возможность получить href, и мы хотим иметь возможность получить или установить связанную переменную.

В следующем примере я попытался использовать более разумные имена переменныхчем b, i и т. д. и упорядочили код с помощью логических функций: извлечение данных из элемента, создание виджетов, разметка виджетов, а затем сохранение данных.

for rownum, item in enumerate(results):
    title = item[3]
    href = item[4]

    var = tk.IntVar(value=0)
    row_label = tk.Label(self.frame, text=rownum)
    title_label = tk.Label(self.frame, text=title)
    cb = tk.Checkbutton(self.frame, text="", variable=var,
                        onvalue=1, offvalue=0)
    button = tk.Button(self.frame, text="LINK",
                       command=lambda rownum=rownum: self.open_link(rownum))

    row_label.grid(row=rownum, column=0)
    cb.grid(row=rownum, column=1)
    title_label.grid(row=rownum, column=2, sticky="w")
    button.grid(row=rownum, column=3)

    # store the data in a dictionary so we can reference it later
    row = {
        "href": href,
        "var": var
    }
    self.rows.append(row)

ДляВ качестве иллюстрации я изменил open_link, чтобы принимать номер строки, а не ссылку. Мы можем использовать номер строки для доступа к href, и я также автоматически выбираю соответствующую кнопку, чтобы доказать, что вы можете.

def open_link(self, rownum):
    link = self.rows[rownum]['href']
    self.rows[rownum]['var'].set(1)
    print(link)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...