Reading through other stackoverflow questions, and other sources I do see that bind can be used to call a function. Currently I'm working on a program that will communicate with a database (most likely mongodb), and so far I've set up a frame that has 2 inputs per row (key-value). I haven't completely decided whether I want one row per document, or one row per field. Right now, if a user has a lot to type then it wouldn't be ideal for them because you can't see everything you write. So what I was thinking is that, if the user clicks on the entry widget, then the box would become bigger and show them everything they have written. My current line of thinking is that maybe I could create another frame for it and somehow pass onto the information to that?
This is what it currently looks like
Then what I'd ideally want it to look like
Here's the code if interested how I made it (Images are from the "CreatePage" section):
from tkinter import *
import tkinter as tk
class Database_Project(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
stack_frame_container = tk.Frame(self)
stack_frame_container.grid_columnconfigure(0, weight=1)
stack_frame_container.grid_rowconfigure(0, weight=1)
stack_frame_container.pack(side="top", fill="both", expand=True)
self.frameslist = {}
for frame in (MainPage, CreatePage):
frame_occurrence = frame.__name__
active_frame = frame(parent=stack_frame_container, controller=self)
self.frameslist[frame_occurrence] = active_frame
active_frame.grid(row=0, column=0, sticky="snew")
self.current_frame("MainPage")
def current_frame(self, frame_occurrence):
active_frame = self.frameslist[frame_occurrence]
active_frame.tkraise()
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label_create = tk.Label(self, text="Create and insert data").grid(row=0, column=0, padx=50, pady=(50,0))
create_button = tk.Button(self, text="CREATE", command=lambda: controller.current_frame("CreatePage")).grid(row=1, column=0)
label_read = tk.Label(self, text="Query over data").grid(row=0, column=1, padx=50, pady=(50,0))
read_button = tk.Button(self, text="READ").grid(row=1, column=1)
label_update = tk.Label(self, text="Modify existing data").grid(row=2, column=0, padx=50, pady=(50,0))
update_button = tk.Button(self, text="UPDATE").grid(row=3, column=0, pady=(0,50))
label_delete = tk.Label(self, text="Remove data").grid(row=2, column=1, padx=50, pady=(50,0))
delete_button = tk.Button(self, text="DELETE").grid(row=3, column=1, pady=(0,50))
class CreatePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.inputlist = []
self.newinputlist = []
labels = [tk.Label(self, text="Enter unique field"), tk.Label(self, text="Enter corresponding the value/s")]
self.inputlist.append(labels[:])
for toplabels in range(1):
self.inputlist[toplabels][0].grid(row=toplabels, column=0, padx=10, pady=5)
self.inputlist[toplabels][1].grid(row=toplabels, column=1, padx=10, pady=5)
for entries in range(2):
for entrynum in range(0, 1):
print("column:", entries)
print("row", entrynum)
self.newinputlist.append(tk.Entry(self, borderwidth=5))
for x in range(len(self.newinputlist)):
self.newinputlist[x].grid(row=1, column=x, padx=10, pady=5)
self.inputlist.append(self.newinputlist[:])
button_input_1 = [tk.Button(self, text="ADD FIELD/VALUE", command=self.add_insert), tk.Button(self, text="BACK", command=lambda: controller.current_frame("MainPage"))]
self.inputlist.append(button_input_1[:])
button_input_2 = [tk.Button(self, text="IMPORT FILE"), tk.Button(self, text="SUBMIT DATA")]
self.inputlist.append(button_input_2[:])
for button in range(len(self.inputlist) - 2, len(self.inputlist)):
self.inputlist[button][0].grid(row=button, column=0, padx=10, pady=5)
self.inputlist[button][1].grid(row=button, column=1, padx=10, pady=5)
def add_insert(self):
add_input = [tk.Entry(self, borderwidth=5), tk.Entry(self, borderwidth=5)]
self.inputlist.insert(-2, add_input)
self.newinputlist.append(add_input)
for widget in self.children.values():
widget.grid_forget()
for index, widgets in enumerate(self.inputlist):
widget_one = widgets[0]
widget_two = widgets[1]
print(str(index), widget_one, widget_two)
widget_one.grid(row=index, column=0, padx=10, pady=5)
widget_two.grid(row=index, column=1, padx=10)
if __name__ == "__main__":
NoSQL_Project = Database_Project()
NoSQL_Project.title("NoSQL Database Project")
NoSQL_Project.mainloop()
It's pointless to resize an Entry
widget since they can only ever hold a single line. I'll give an example using the Text
widget instead, though the technique works with any widget.
There's really no trick, just bind to <FocusIn>
and <FocusOut>
. In the following example I've created two Text
widgets that have this resize behavior:
import tkinter as tk
def resizer(event):
if event.widget == event.widget.focus_get():
event.widget.configure(height=8)
else:
event.widget.configure(height=1)
root = tk.Tk()
root.geometry("400x200")
text1 = tk.Text(root, height=1, width=20)
text2 = tk.Text(root, height=1, width=20)
text1.pack(side="left")
text2.pack(side="right")
for widget in (text1, text2):
widget.bind("<FocusIn>", resizer)
widget.bind("<FocusOut>", resizer)
root.mainloop()
The actual behavior depends on how you've laid out your widget. This could cause widgets to jump around or the window resize, but every app will be different so it's hard to give a solution that works everywhere.