1

I have a list out_list = ["item1",item2","item3",....] which I am trying to add text_box and Entry for each item as the following:

enter image description here

But when I'm trying to get from the text box, text_box.get("1.0",'end-1c'), I am getting all of the list as one string.

Thanks for the help!

        for i in range(0,len(out_list)):
            text_box.window_create(text_box.index("end"), window=tk.Button(text_box, text="Copy Variable",command=buttonClick))
            text_box.window_create(text_box.index("end"), window=tk.Entry(text_box, text=str(out_list[i])))
            text_box.window_create(text_box.index("end"),text_box.insert(END, out_list[i]), window=text_box_value)
        text_box.insert(END,'\n')  # adds text to text box
acw1668
  • 40,144
  • 5
  • 22
  • 34
David
  • 111
  • 1
  • 2
  • 8
  • `text1_id = text_box.window_create(..)` and now you can access first textbox using `text1_id` – furas Apr 26 '21 at 12:15
  • or maybe you should first create `entry_1 = tk.Entry(..)` and keep it on list - to have access to this Entry, or to use `command=lambda:buttonClick(entry_1)` – furas Apr 26 '21 at 12:19
  • or maybe you should use `Frame` to group elements `Button`, `Entry`, `text` and create own widget (with all needed functions for single row) and use this widget in `for`-loop – furas Apr 26 '21 at 12:21
  • instead of `for i in range(0,len(out_list))` you could learn to use `for item in out_list:` – furas Apr 26 '21 at 12:21

1 Answers1

1

You should first create Entry

entry = tk.Entry(text_box)
entry.insert("end", item)

and later you could use it in

command=lambda:button_click(entry))

but it is inside for-loop and lambda doesn't copy value from entry to code button_click(entry) so it keeps only reference to entry and this entry is changing in loop - and finally all lambda has reference to the same variable which has last value. You have to use extra variable to copy object.

command=lambda x=entry:button_click(x))

Minimal working code

import tkinter as tk   # PEP8: `import *` not preferred

# --- functions --- (PEP8: lower_case_names)

def button_click(entry):
    print('ENTRY:', entry.get())

# --- main ---

out_list = ["item1", "item2", "item3", ]  # PEP8: spaces after comma

root = tk.Tk()

text_box = tk.Text(root)
text_box.pack()

for item in out_list:
    print(item)
    
    entry = tk.Entry(text_box)
    entry.insert("end", item)
    
    button = tk.Button(text_box, text="Copy Variable", command=lambda x=entry:button_click(x))
    
    text_box.window_create(text_box.index("end"), window=button)
    text_box.window_create(text_box.index("end"), window=entry)
    #text_box.window_create(text_box.index("end"), text_box.insert('end', item), window=text_box_value)
    text_box.insert("end", item)
    text_box.insert("end", '\n')  # adds text to text box

root.mainloop()

EDIT:

You could also use Frame to build own widget with Button, Entry, Label and button_click and later use this widget.

It can be simpler to add or hide widget.

import tkinter as tk   # PEP8: `import *` not preferred

# --- classes --- (PEP8: CamelCaseNames) 

class MyWidget(tk.Frame):

    def __init__(self, master, text, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
               
        self.button = tk.Button(self, text="Copy Variable", command=self.button_click)
        self.button.pack(side="left")
    
        self.entry = tk.Entry(self)
        self.entry.insert("end", text)
        self.entry.pack(side="left")
        
        self.label = tk.Label(self, text=text)
        self.label.pack(side="left")
        
    def button_click(self):
        print('ENTRY:', self.entry.get())
        #self.button["text"] = self.entry.get()
    
# --- functions --- (PEP8: lower_case_names)

def copy_all_variables():
    for widget in all_widgets:
        print(widget.entry.get())
        #widget.button_copy()

def add_widget():
    item = "item" + str(len(all_widgets)+1)
    widget = MyWidget(frame_widget, text=item)
    widget.pack(fill='x')
    all_widgets.append(widget)

def remove_widget():
    if all_widgets:
        all_widgets[-1].destroy()
        del all_widgets[-1]

# --- main ---

out_list = ["item1", "item2", "item3", ]  # PEP8: spaces after comma

root = tk.Tk()

# - version 1 -

tk.Label(root, text="Text Box + window_create()", bg="#8080ff").pack(fill='x', expand=True)

text_box = tk.Text(root)
text_box.pack()

all_widgets_1 = []

for item in out_list:
    widget = MyWidget(text_box, text=item)
    text_box.window_create(text_box.index("end"), window=widget)
    text_box.insert("end", '\n')  # adds text to text box
    all_widgets_1.append(widget)

# - version 2 -

tk.Label(root, text="Frame + pack()", bg="#8080ff").pack(fill='x', expand=True)

all_widgets = []

frame_widget = tk.Frame(root)
frame_widget.pack(fill='x')

for item in out_list:
    widget = MyWidget(frame_widget, text=item)
    widget.pack(fill='x')
    all_widgets.append(widget)
   
frame_buttons = tk.Frame(root)
frame_buttons.pack()   

button_copy = tk.Button(frame_buttons, text="Copy All Variables", command=copy_all_variables)
button_copy.pack(side="left")

button_add = tk.Button(frame_buttons, text="Add Widget", command=add_widget)
button_add.pack(side="left")

button_remove = tk.Button(frame_buttons, text="Remove Widget", command=remove_widget)
button_remove.pack(side="left")

# - 

root.mainloop()

enter image description here

And when you put Button and Entry directly to Text then you can write text between widgets.

enter image description here

furas
  • 134,197
  • 12
  • 106
  • 148
  • Hi furas, that's indeed what I meant, works perfect, I added a search to that list, but I am trying to "clean" the widgets once a updated list. I have tried the following: " for label in root.pack_slaves(): if label.pack_fo print(label) label.destroy()" – David Apr 28 '21 at 06:57
  • 1
    I don't know if I understand example code. if you mean to remove text from all labels then assing empty string - `for widget in all_widgets: widget.label["text"] = ""`. If you mean to remove all widgets then `for widget in all_widgets: widget.destroy()` and `all_widgets = []`. – furas Apr 28 '21 at 07:38
  • 1
    i noticed i inserted the wrong code - without buttons `Add Widget` and `Remove Widget` - but I put image with these buttons. Now code has these buttons. – furas Apr 28 '21 at 07:43