How to stretch the buttons so that they fit the entire frame? - python

import tkinter as tk
window = tk.Tk()
for i in range(3):
for j in range(3):
window.columnconfigure(i,weight = 1, minsize=50)
window.rowconfigure(j,weight = 1, minsize = 50)
frame = tk.Frame(relief=tk.RAISED, borderwidth=3, padx=5, pady=5)
frame.grid(row=i, column=j,sticky = "nsew")
but = tk.Button(text=f"row {i+1}\n column {j+1}", master = frame)
but.grid(row=0, column=0,sticky = "nsew")
window.mainloop()
even if I put sticky="nsew" for the button, it does not stretch.

Related

How to create Tkinter Tab frame with different (dynamic) heights

I am trying to create Tabs in python tkinter. I would like the Tab's height to size dynamically based on its content. Below is a sample of my code
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady = 5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady= 5)
nbframe1 = Frame(notebook1, bg = 'white')
nbframe2 = Frame(notebook1, bg = 'grey')
nbframe1.pack(fill ='both', expand=1)
nbframe2.pack(fill ='both', expand=1)
notebook1.add(nbframe1, text= 'A Search')
notebook1.add(nbframe2, text= 'B Search')
a_label = Label(nbframe1, text= 'A_Tag', bg = 'white')
a_label.grid(row = 0, column = 0, sticky=W, padx=5)
b_label = Label(nbframe1, text= 'B_Tag', bg = 'white')
b_label.grid(row = 1, column = 0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable = a_text, width=50)
a_entry.grid(row = 0, column = 1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable = b_text, width=25)
b_entry.grid(row = 1, column = 1, sticky=W, padx=5)
root.mainloop()
From my code, the Tabs created have same height even though one is empty. This is based on the height of the Tab with content. How can i set it so that each Tab's height is based only on the contents.
You can bind a function to the virtual event <<NotebookTabChanged>> to adapt the height of the notebook to the currently selected tab using the height option of the notebook:
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select()) # get selected tab
event.widget.configure(height=tab.winfo_reqheight()) # resize notebook
With your example:
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select())
event.widget.configure(height=tab.winfo_reqheight())
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady=5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady=5)
nbframe1 = Frame(notebook1, bg='white')
nbframe2 = Frame(notebook1, bg='grey')
notebook1.add(nbframe1, text='A Search')
notebook1.add(nbframe2, text='B Search')
a_label = Label(nbframe1, text='A_Tag', bg='white')
a_label.grid(row=0, column=0, sticky=W, padx=5)
b_label = Label(nbframe1, text='B_Tag', bg='white')
b_label.grid(row=1, column=0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable=a_text, width=50)
a_entry.grid(row=0, column=1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable=b_text, width=25)
b_entry.grid(row=1, column=1, sticky=W, padx=5)
root.update_idletasks() # force display update so that the initial tab is displayed correctly
notebook1.bind('<<NotebookTabChanged>>', on_change_tab) # binding to update the height
root.mainloop()

Adding a scrollbar to GUI labels not working

I have tried adding a scrollbar to my GUI but it keeps returning a small canvas which my labels don't fit.
Below is my code using Python.
import tkinter as tk
from tkinter import Canvas, Frame, ttk
from tkinter.constants import ANCHOR, BOTH, LEFT, RIGHT, VERTICAL, Y
root = tk.Tk()
#create a Main Frame
main_frame = tk.Frame(root)
main_frame.grid(row=2, column=0, pady=(5,0), sticky="nw")
main_frame.grid_rowconfigure(0, weight=1)
main_frame.grid_columnconfigure(0, weight=1)
#create a canvas
my_canvas = Canvas(main_frame, bg="yellow")
my_canvas.grid(row=0, column=0, sticky="news")
#Scrollbar
my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.grid(row=0, column=0, sticky="ns")
#configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#create another frame inside canvas
second_frame = Frame(my_canvas)
#add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw")
# Labels
tk.Label(root, text="Decision Support System").grid(
column=0, row=0, sticky="", padx=50)
tk.Label(root, text="""This is a simple application that will help in decision making on whether to adopt a technology based on criteria listed below, you are rate each criteria 1-5
1- not important, 2- slightly important, 3- moderately important, 4-important, 5- very important""").grid(column=0, row=1)
tk.Label(root, text="What type of technology are you trying to invest in?").grid(
column=0, row=2, sticky="w", pady=20, padx=10)
tk.Label(root, text="CA1- Technology Predictors, Group score[35], Coefficient = 0.200").grid(
column=0, row=3, sticky="", pady=10, padx=10)
tk.Label(root, text="Ca1.1-Level of training required : is training of staff going to be thorough?").grid(
column=0, row=4, sticky="w", pady=10, padx=10)
#GUI window
root.mainloop()
And this is what it looks like:
It has a total of 27 rows.
Does this work for you?
I've added a horizontal scrollbar and placed all labels into canvas.
import tkinter as tk
from tkinter import Canvas, Frame, ttk
from tkinter.constants import ANCHOR, BOTH, LEFT, RIGHT, VERTICAL, HORIZONTAL, X, Y
root = tk.Tk()
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
my_canvas = Canvas(root, bg = "yellow")
my_canvas.grid(row = 0, column = 0, sticky = "news")
#Scrollbar
v_scrollbar = ttk.Scrollbar(root, orient = VERTICAL, command = my_canvas.yview)
v_scrollbar.grid(row = 0, column = 1, sticky="ns")
my_canvas.configure(yscrollcommand = v_scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#Scrollbar
h_scrollbar = ttk.Scrollbar(root, orient = HORIZONTAL, command = my_canvas.xview)
h_scrollbar.grid(row = 1, column = 0, sticky="ew")
my_canvas.configure(xscrollcommand = h_scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#create a Main Frame
main_frame = tk.Frame(my_canvas)
main_frame.grid(row = 0, column = 0, sticky = "nsew")
# Labels
tk.Label(main_frame, text = "Decision Support System").grid(
column = 0, row = 0, sticky = "", padx = 50)
tk.Label(main_frame, text="""This is a simple application that will help in decision making on whether to adopt a technology based on criteria listed below, you are rate each criteria 1-5
1- not important, 2- slightly important, 3- moderately important, 4-important, 5- very important""").grid(
column = 0, row = 1)
tk.Label(main_frame, text="What type of technology are you trying to invest in?").grid(
column = 0, row = 2, sticky="w", pady = 20, padx = 10)
tk.Label(main_frame, text="CA1- Technology Predictors, Group score[35], Coefficient = 0.200").grid(
column = 0, row = 3, sticky="", pady = 10, padx = 10)
tk.Label(main_frame, text="Ca1.1-Level of training required : is training of staff going to be thorough?").grid(
column = 0, row = 4, sticky = "w", pady = 10, padx = 10)
my_canvas.create_window((0,0), window = main_frame, anchor = "nw")
root.geometry("836x221")
root.mainloop()

How to position widgets (e.g. buttons, tabels or entry's) within a tkinter multi-frame application?

I'm currently trying to position some widgets at the top of a frame through sticky = 'n'. That frame is positioned beside a bigger frame. However, the widgets remain centered in their own frame. I would like to keep open the space below the e1-e4 labels and entries in the code below:
import tkinter as tk
master = tk.Tk()
# frame construction
topframe=tk.Frame(master,width = 600, height = 50,bg='red')
topframe.grid(row = 0, column = 0, columnspan=2)
leftframe = tk.Frame(master)
leftframe.grid(row = 1, column = 0)
rightframe = tk.Frame(master)
rightframe.grid(row = 1, column = 1)
bottomframe = tk.Frame(master,width = 600, height = 50, bg='green')
bottomframe.grid(row = 2, column = 0, columnspan=2)
# filling in the frame
tk.Label(leftframe, text="e1:").grid(row=1, sticky='n')
tk.Label(leftframe, text="e2:").grid(row=2, sticky='n')
tk.Label(leftframe, text="e3:").grid(row=3, sticky='n')
tk.Label(leftframe, text="e4:").grid(row=4, sticky='n')
canvas=tk.Canvas(rightframe, width=300, height=300,
borderwidth = 1, bg ='light grey',
highlightthickness=0, highlightbackground="blue")
canvas.grid(row=0, column=0)
e1 = tk.Entry(leftframe)
e2 = tk.Entry(leftframe)
e3 = tk.Entry(leftframe)
e4 = tk.Entry(leftframe)
e1.grid(row=1, column=1, sticky='n')
e2.grid(row=2, column=1, sticky='n')
e3.grid(row=3, column=1, sticky='n')
e4.grid(row=4, column=1, sticky='n')
master.mainloop()

Place a single scrollbar for the frames that are displayed in a single window

There are two frames that have to be displayed in a single window. The second exceeds the display size and the scrollbar has to placed for the entire window.
from tkinter import *
rectangle_values = []
k = 0
def open_window(rectangles):
global k
window.title('Rectangles')
print(rectangles)
for i in range(0, int(rectangles) * 2):
if (i % 2) == 0:
l4 = Label(frame2, text="Size of rectangle:")
l4.grid(row=i, column=0)
en = Entry(frame2)
en.grid(row=i, column=1)
frame2.tkraise()
b4 = Button(frame2, text="Back", width=12, command=lambda: (frame1.tkraise(), window.title('Rectangle Configuration')))
b4.grid(row=int(rectangles) * 2 + 1, column=1)
k = int(rectangles)
def myfunction(event):
canvas.configure(scrollregion=canvas.bbox("all"),width=220,height=700)
def _on_mousewheel(event):
canvas.yview_scroll(-1*(event.delta/120), "units")
window = Tk()
window.geometry('800x800')
frame1 = Frame(window)
frame1.grid(row = 2, column = 0)
frame2 = Frame(window)
frame2.grid(row = 10, column = 0)
frame1.tkraise()
l3 = Label(frame1, text="Number of Rectangles:")
l3.grid(row=0, column=0)
# defining entries
rectangles = StringVar()
e3 = Entry(frame1, textvariable=rectangles)
e3.grid(row=0, column=1)
# Defining buttons
b1 = Button(frame1, text='Submit', width=12, command=lambda: open_window(rectangles.get()))
b1.grid(row=3, column=1)
window.title("Rectangle Configuration")
window.mainloop()
So, this is code here. When the number of rectangle is more than 18, we need a scrollbar.
myframe=Frame(window)
canvas=Canvas(myframe)
frame=Frame(canvas)
myscrollbar=Scrollbar(myframe,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set)
canvas.bind_all('<MouseWheel>', lambda event: canvas.yview_scroll(int(-1*(event.delta/120)), "units"))
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((0,0),window=frame,anchor='nw')
frame.bind("<Configure>",myfunction)
window.bind("<MouseWheel>", myfunction)
myframe.grid(row=3, column=7)
I added this but the scrollbar is between the two frames. How do I put a scrollbar that is for the entire window?
I think you shold use another approach, try to use more the Canvas widget, do somethink like this is more easier.
import tkinter as tk
def open_window(rect):
window.title('Rectangles')
print(rect)
x, y = 100, 50
for i in range(0, rect * 2):
if (i % 2) == 0:
l4 = tk.Label(canvas, text="Size of rectangle:")
canvas.create_window(0, y, window=l4, anchor=tk.NW)
en = tk.Entry(canvas)
canvas.create_window(x, y, window=en, anchor=tk.NW)
y += 20
canvas.configure(scrollregion=canvas.bbox("all"))
window = tk.Tk()
window.configure()
ws = window.winfo_screenwidth()
hs = window.winfo_screenheight()
w = 500 # width for the Tk root
h = 300 # height for the Tk root
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
window.geometry('%dx%d+%d+%d' % (w, h, x, y))
canvas = tk.Canvas(window, bg="black", width=500, height=300)
canvas.pack()
canvas_scroll = tk.Scrollbar(canvas, command=canvas.yview)
canvas_scroll.place(relx=1, rely=0, relheight=1, anchor=tk.NE)
canvas.configure(yscrollcommand=canvas_scroll.set, scrollregion=(0, 0, 500, 300))
rect_var = tk.IntVar()
entry_rect_number = tk.Entry(canvas, textvariable=rect_var)
canvas.create_window(0, 0, window=entry_rect_number, anchor=tk.NW)
sumbit_button = tk.Button(canvas, text="sumbit", command=lambda: open_window(rect_var.get()))
canvas.create_window(0, 20, window=sumbit_button, anchor=tk.NW)
# Here is the frame
canvas_frame1 = tk.Canvas(canvas, bg="red", width=150, height=290)
frame_scroll = tk.Scrollbar(canvas_frame1, command=canvas_frame1.yview)
frame_scroll.place(relx=1, rely=0, relheight=1, anchor=tk.NE)
canvas_frame1.configure(yscrollcommand=frame_scroll.set, scrollregion=(0, 0, 200, 400))
canvas_frame1.create_oval(0, 0, 50, 50)
canvas.create_window(250, 0, window=canvas_frame1, anchor=tk.NW)
canvas.bind_all('<MouseWheel>', lambda event: canvas.yview_scroll(int(-1*(event.delta/120)), "units"))
window.mainloop()
I don't know if there is a way for scroll a Frame from the main window but my advice is to create a Canvas where you put all your widgets and add a scrollbar to the Canvas so that all the widgets inside the Canvas are easily scrolled.
for more infos about the Canvas and all its methods see this site

Checkbox not showing up python

I am making a GUI that will control a robot.
This is my code so far:
from Tkinter import * #Importing TKinter
class Application(Frame): #Making a frame
def __init__(self, master=None):
Frame.__init__(self, master)
self.master.title("Vinny's Myro Controller Version 0.1") #Setting the name of the program/window
self.master.geometry("550x365+300+300") #Window dimensions
self.master.rowconfigure(0, weight=2) #how much space the rows take
self.master.columnconfigure(0, weight=1) #how much space the columns take
''' \/ BOTTOM BUTTONS \/ '''
self.master.button1 = Button(master, text = "Take a Picture") #Bottom button that is supposed to take a pic.
self.master.button1.grid(row=6, column=0, sticky=W+E)
self.master.button2 = Button(master, text = "Honk the Horn") #Bottom button that is supposed to honk the horn.
self.master.button2.grid(row=6, column=1, sticky=W+E)
self.master.button3 = Button(master, text = "Get Sensor Data") #Bottom button that is supposed to get data from the sensors.
self.master.button3.grid(row=6, column=2, sticky=W+E)
''' /\ BOTTOM BUTTONS /\ '''
''' \/ LEFT RED FRAME THAT CONTAINS THE ARROWS THAT WILL MOVE THE ROBOT \/ '''
self.frame1 = Frame(master, bg="red") #Background color
self.frame1.grid(row = 0, column = 0, rowspan = 1, columnspan = 1, sticky = W+E+N+S, padx=10, pady=10)
self.frame1.forward = Button(self.frame1, text = "Forward", width=30, height=3) #Forward Button
self.frame1.forward.place(x=63, y=75) #Button Position
self.frame1.right = Button(self.frame1, text = "Right", width=12, height=3) #Right Button
self.frame1.right.place(x=189, y=131) #Button Position
self.frame1.backward = Button(self.frame1, text = "Backward", width=30, height=3) #Backward Button
self.frame1.backward.place(x=63, y=187) #Button Position
self.frame1.left = Button(self.frame1, text = "Left", width=12, height=3) #Left Button
self.frame1.left.place(x=63, y=131) #Button Position
''' /\ LEFT RED FRAME THAT CONTAINS THE ARROWS THAT WILL MOVE THE ROBOT /\ '''
self.frame2 = Frame(master, bg="green")
self.frame2.grid(row = 0, column = 1, rowspan = 3, columnspan = 3, sticky = W+E+N+S, padx=10, pady=10)
self.frame2.button5 = Button(self.frame2, text = "test")
self.frame2.button5.grid(row=6, column=2)
self.frame2.light = BooleanVar()
self.frame2.chk1 = Checkbutton(self, text = "Lights", variable = self.frame2.light, command = 1+1)
self.frame2.chk1.grid(row = 0, column = 3, padx=10, pady = 10)
root = Tk()
app = Application(master=root)
app.mainloop()
Note this piece of code:
self.frame2.light = BooleanVar()
self.frame2.chk1 = Checkbutton(self, text = "Lights", variable = self.frame2.light, command = 1+1)
self.frame2.chk1.grid(row = 0, column = 3, padx=10, pady = 10)
Somehow, I can place a button inside my frame, but not a checkbox. I need this checkbox in order to get data from the robot's sensors.
I've tried using grid and place.
Could anybody help me?
Screenshot:
http://d.pr/i/iRX4
Thanks
The problem is that you are creating the checkbutton as a child of self rather than as a child of self.frame2. Change the checkbutton to be:
self.frame2.chk1 = Checkbutton(self.frame2, ...)

Categories

Resources