tkinter: динамически вставлять кнопку в текстовое поле рядом с текстом в каждой строке - PullRequest
0 голосов
/ 06 ноября 2018

Вопрос:

У меня есть цикл for, который добавляет текст в текстовое поле. Я хочу крайнюю кнопку справа после текста и перед каждой итерацией в текстовом поле.

Также возможно ли присвоить кнопке какой-либо тег, являющийся текстом перед ним? Таким образом, для каждой итерации кнопка вызывает функцию и передает текст перед ней.

Ожидаемое изображение:

enter image description here

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Вы можете использовать табуляцию, чтобы выровнять что-то по правому краю. Единственная хитрость в том, что вам нужно пересчитывать табуляцию при изменении размера окна. Вы можете сделать это, связавшись с событием <Configure>. Если вы поместите окно сразу после вкладки и до новой строки, оно будет выровнено по правому краю.

Вы можете связать лямбда-функцию с кнопкой, чтобы дать вам возможность определить данные для отправки в обратный вызов.

Вот простой пример:

import tkinter as tk

def reset_tabs(event):
    '''Add a tabstop at the right edge of the widget'''
    right_margin = event.width - 8
    if right_margin <= 0: return
    tabs = (right_margin, "right")
    event.widget.configure(tabs=tabs)

def callback(text):
    print("you clicked {}".format(text))

root = tk.Tk()
text = tk.Text(root)
text.pack(fill="both", expand=True)
text.bind("<Configure>", reset_tabs)

for i in range(10):
    item = "this is item {}".format(i+1)
    text.insert("end", item + "\t\n")
    button = tk.Button(text, text="x", padx=2, pady=2,
                       cursor="left_ptr",
                       bd=1, highlightthickness=0,
                       command = lambda text=item: callback(text))
    text.window_create("end-2c", window=button)

root.mainloop()

Приведенный выше код приводит к окну, подобному этому:

enter image description here

0 голосов
/ 06 ноября 2018

Обновление:

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

import tkinter as tk

list_of_file_data = [["Data set 1!", "This is the contents of data set 1.", True],
                     ["Data set 2!", "This is the contents of data set 2.", True],
                     ["Data set 3!", "This is the contents of data set 3.", True]]

class Example(tk.Tk):
    def __init__(self):

        tk.Tk.__init__(self)
        self.geometry("350x200")
        self.txt_frame = tk.Frame(self)
        self.txt_frame.grid(row=1, column=1)
        self.txt_box = tk.Text(self.txt_frame, width=40, height=15)
        self.txt_box.pack()
        self.update_textbox()

    def update_textbox(self):
        self.txt_box.delete(1.0, "end")
        for ndex, data_set in enumerate(list_of_file_data):
            if data_set[2] == True:
                self.txt_box.insert("end", "{}".format(data_set[0]))
                self.txt_box.window_create(self.txt_box.index("end"), window = tk.Button(self.txt_box, text="F", command=lambda x=ndex: self.toggle_data(x)))
                self.txt_box.insert("end", "\n")
                self.txt_box.insert("end", "    {}\n\n".format(data_set[1]))
            else:
                self.txt_box.insert("end", "{}".format(data_set[0]))
                self.txt_box.window_create(self.txt_box.index("end"), window = tk.Button(self.txt_box, text="F", command=lambda x=ndex: self.toggle_data(x)))
                self.txt_box.insert("end", "\n...\n")


    def toggle_data(self, ndex):
        if list_of_file_data[ndex][2] == True:
            list_of_file_data[ndex][2] = False
        else:
            list_of_file_data[ndex][2] = True
        self.update_textbox()


if __name__ == "__main__":
    Example().mainloop()

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

Если вы изменили метод update_textbox() на этот, он поместит кнопки слева.

def update_textbox(self):
    self.txt_box.delete(1.0, "end")
    for ndex, data_set in enumerate(list_of_file_data):
        if data_set[2] == True:
            self.txt_box.window_create(self.txt_box.index("end"), window = tk.Button(self.txt_box, text="F", command=lambda x=ndex: self.toggle_data(x)))
            self.txt_box.insert("end", "{}".format(data_set[0]))
            self.txt_box.insert("end", "\n")
            self.txt_box.insert("end", "    {}\n\n".format(data_set[1]))
        else:
            self.txt_box.window_create(self.txt_box.index("end"), window = tk.Button(self.txt_box, text="F", command=lambda x=ndex: self.toggle_data(x)))
            self.txt_box.insert("end", "{}".format(data_set[0]))
            self.txt_box.insert("end", "\n...\n")

Результаты:

enter image description here

enter image description here

...

...

...

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

import tkinter as tk

list_of_file_data = [["Data set 1!", "This is the contents of data set 1.", True],
                     ["Data set 2!", "This is the contents of data set 2.", True],
                     ["Data set 3!", "This is the contents of data set 3.", True]]

class Example(tk.Tk):
    def __init__(self):

        tk.Tk.__init__(self)
        self.geometry("350x200")
        self.tbl_view = True
        self.tbl_frame = tk.Frame(self)
        self.tbl_frame.grid(row=1, column=0, sticky="nsew")
        self.txt_frame = tk.Frame(self)
        self.txt_frame.grid(row=1, column=1)
        tk.Button(self, text="Toggle Table of context", command=self.show_hide_tbl).grid(row=0, column=0, columnspan=2, sticky="ew")
        self.txt_box = tk.Text(self.txt_frame, width=30, height=10)
        self.txt_box.pack()
        self.update_textbox()

    def update_textbox(self):
        self.tbl_frame.destroy()
        self.tbl_frame = tk.Frame(self)
        if self.tbl_view == True:
            self.tbl_frame.grid(row=1, column=0, sticky="nsew")

        self.txt_box.delete(1.0, "end")
        for ndex, data_set in enumerate(list_of_file_data):
            tk.Button(self.tbl_frame, text=data_set[0], command=lambda x=ndex: self.toggle_data(x)).pack()
            if data_set[2] == True:
                self.txt_box.insert("end", "{}\n".format(data_set[0]))
                self.txt_box.insert("end", "    {}\n\n".format(data_set[1]))

    def toggle_data(self, ndex):
        if list_of_file_data[ndex][2] == True:
            list_of_file_data[ndex][2] = False
        else:
            list_of_file_data[ndex][2] = True
        self.update_textbox()

    def show_hide_tbl(self):
        if self.tbl_view == True:
            self.tbl_frame.grid_forget()
            self.tbl_view = False
        else:
            print("Else")
            self.tbl_frame.grid(row=1, column=0, sticky="nsew")
            self.tbl_view = True


if __name__ == "__main__":
    Example().mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...