I am trying to display another frame in the bottom left corner, however when I .pack() it, it does not display.
Here is my code:
import tkinter as tk
import customtkinter
window = customtkinter.CTk()
window.geometry("1900x980")
#customtkinter.set_appearance_mode("dark")
mainFrame = customtkinter.CTkFrame(window, width=1900, height=980)
mainFrame.pack()
mainFrame.pack_propagate(0)
topFrame = customtkinter.CTkFrame(mainFrame, width=1870, height=110, corner_radius=10)
topFrame.pack(side=tk.TOP, padx=10, pady=10)
topFrame.pack_propagate(0)
leftFrame = customtkinter.CTkFrame(mainFrame, width=400, height=825, corner_radius=10)
leftFrame.pack(side=tk.LEFT, padx=15, pady=5)
leftFrame.pack_propagate(0)
rightFrame = customtkinter.CTkFrame(mainFrame, width=1460, height=825, corner_radius=10)
rightFrame.pack(side=tk.RIGHT, padx=15, pady=5)
rightFrame.pack_propagate(0)
bottomLeftFrame = customtkinter.CTkFrame(mainFrame, width=400, height=20, corner_radius=10, bg_color="red")
bottomLeftFrame.pack(side=tk.LEFT)
bottomLeftFrame.pack_propagate(0)
window.mainloop()
To my understanding, if two objects are assigned side=tk.LEFT, then the second will be placed below the first one on the left hand side. However, this does not happen. Please see my output here.
Does any one know why this is? I have adjusted the height of both the left hand side frames so they should fit in the window.
Related
The 2 buttons should take each of the half of the window, one on the left, one on the right. The height is fixed all time. With .grid() nor .place() I can come to that result. The red bar is the color of the frame where the buttons are placed on. The buttons resize in width with the window, but keep their constant height.
How to?
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red')
frame.pack(fill='both', expand=True)
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky='nsew')
button2.grid(row=0, column=1, sticky='nsew')
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
root.mainloop()
Thx.
In the mean time I got this:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(fill='both')
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.place(relwidth=0.5, relx=0, relheight=1)
button2.place(relwidth=0.5, relx=0.5, relheight=1)
root.mainloop()
Assuming that the buttons are the only widgets in the frame (ie: you are making a toolbar), I would use pack. grid will also work, but it requires one extra line of code.
Using pack
Here's a version with pack. Notice that the frame is packed along the top and fills the window in the "x" direction. The buttons each are instructed to expand (ie: receive extra, unused space) and to fill the space allocated to them in the "x" direction.
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.pack(side="left", fill="x", expand=True)
button2.pack(side="right", fill="x", expand=True)
root.mainloop()
Using Grid
A version with grid is similar, but you must use columnconfigure to give a non-zero weight to the two columns:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky="ew")
button2.grid(row=0, column=1, sticky="ew")
frame.grid_columnconfigure((0, 1), weight=1)
root.mainloop()
I am experimenting with Tkinter, as I was trying to place tree frames. Two frames must be placed side by side: the red one and the blue one. (see frame image). I place this two frames with this istructions:
redFrame = tk.Frame(master=masterFrame, bg='red')
redFrame.pack_propagate(0)
redFrame.pack(fill='both', side='left', expand='True')
blueFrame = tk.Frame(master=masterFrame, bg='blue')
destFrame.pack_propagate(0)
destFrame.pack(fill='both', side='right', expand='True')
Now I want to put another frame (green) inside the red one, placed on the left side of the main interface:
greenFrame = tk.Frame(master=masterFrame, width=100, height=100, bg='green')
greenFrame.pack_propagate(0)
greenFrame.pack(side='bottom', padx=0, pady=0)
The problem is that I can't choose its position. It still remain in the top side of the window and centered.
If I change the padx parameter nothing change.
If i change the pady parameter, the frame change its Y position. Why this not appened with the X posistion?
Widgets will by default be centered in their allocated space within the container.
Your code at the moment doesn't work, so I've changed it to this (I think it mimics what you're saying you currently have):
import tkinter as tk
root = tk.Tk()
root.geometry("600x400")
redFrame = tk.Frame(root, bg='red')
redFrame.pack_propagate(0)
redFrame.pack(fill='both', side='left', expand='True')
blueFrame = tk.Frame(root, bg='blue')
blueFrame.pack_propagate(0)
blueFrame.pack(fill='both', side='right', expand='True')
greenFrame = tk.Frame(redFrame, width=100, height=100, bg='green')
greenFrame.pack_propagate(0)
greenFrame.pack(side='top', padx=0, pady=0)
root.mainloop()
If you run this code, the greenFrame will appear as your image shows, at the top and centered inside redFrame.
If you want greenFrame to appear at the top left of redFrame, you can change the anchor point of the frame:
greenFrame = tk.Frame(redFrame, width=100, height=100, bg='green')
greenFrame.pack_propagate(0)
greenFrame.pack(side='top', padx=0, pady=0, anchor='w')
That is because when you do side="top" using pack, the widget gets allocated an entire strip of horizontal space. It gets centered within that space by default:
If you do side="left", then the widget gets allocated an entire strip of vertical space, and it gets centered in that space by default.
However in both cases you can change the anchor point, so that your component is placed differently within that allocated spaces.
This is the code which achieves what (I think) you want:
import tkinter as tk
root = tk.Tk()
root.geometry("600x400")
redFrame = tk.Frame(root, bg='red')
redFrame.pack_propagate(0)
redFrame.pack(fill='both', side='left', expand='True')
blueFrame = tk.Frame(root, bg='blue')
blueFrame.pack_propagate(0)
blueFrame.pack(fill='both', side='right', expand='True')
greenFrame = tk.Frame(redFrame, width=100, height=100, bg='green')
greenFrame.pack_propagate(0)
greenFrame.pack(side='top', padx=0, pady=0, anchor='w')
root.mainloop()
Using tkinter, I wanted to make an interface containing a few buttons on the left, which would be fairly static and align with the widgets on the right fairly nicely.
On the right, I wanted an Entry widget above a Text widget, both of which would resize accordingly (the Entry widget only on the X axis).
This code accomplishes most of that, except the Text widget does not resize and the Entry widget only resizes to align with the Text widget. Upon trying to column/rowconfigure the root, the top frame resizes awkwardly.
Here's a picture of the tkinter interface from this code:
from tkinter import *
def main():
root = Tk()
root.geometry("300x400")
framet = Frame(root)
frameb = Frame(root)
framet.grid(row=0, column=0, sticky='ew')
frameb.grid(row=1, column=0, sticky='news')
button1 = Button(framet, text='one', width=8)
button1.grid(row=0, column=0)
button2 = Button(frameb, text='two', width=8)
button2.grid(row=1, column=0, sticky='n')
entry1 = Entry(framet)
entry1.grid(row=0, column=1, sticky='ew')
text1 = Text(frameb, highlightbackground='black', highlightthickness=1)
text1.grid(row=1, column=1, sticky='news')
framet.columnconfigure(1, weight=1)
if __name__ == '__main__':
main()
As you can see, the Entry and Text widgets do not resize. How could I accomplish this whilst still having the Buttons remain static, and not moving anything (only resizing)?
Would this work for you? I changed the lines with # comments, I think, I can't really remember what I did I just tryed to get it working, one problem which I'm not happy with though is the entry widget is not the same height as the button, I guess you could manually set its height but..
from tkinter import *
def main():
root = Tk()
root.grid_columnconfigure(1,weight=1) # the text and entry frames column
root.grid_rowconfigure(0,weight=1) # all frames row
buttonframe = Frame(root)
buttonframe.grid(row=0, column=0, sticky="nswe")
entry_text_frame = Frame(root)
entry_text_frame.grid(row=0, column=1, sticky="nswe")
entry_text_frame.grid_columnconfigure(0,weight=1) # the entry and text widgets column
entry_text_frame.grid_rowconfigure(1,weight=1) # the text widgets row
button1 = Button(buttonframe, text='one', width=8)
button1.grid(row=0, column=0, sticky='nswe')
button2 = Button(buttonframe, text='two', width=8)
button2.grid(row=1, column=0, sticky='nswe')
entry1 = Entry(entry_text_frame)
entry1.grid(row=0, column=0, sticky='nswe')
text1 = Text(entry_text_frame, highlightbackground='black', highlightthickness=1)
text1.grid(row=1, column=0, sticky='news')
root.geometry("300x400")
if __name__ == '__main__':
main()
I'm quite new to Tkinter but I have been practicing it for a bit now but whenever I try to move a label in a frame with grid geometry by specifying row and column, the label just stays in the middle.
In the code below, I try specifying the row and column for the name label which is in the top middle frame but it never moves. It just stays in the middle.
from tkinter import*
root=Tk()
frame_topleft = Frame(root, height=150, width=50, bg = "green")
frame_topmiddle = Frame(root, height=150, width=250, bg="red")
frame_topright = Frame(root, height=150, width=250, bg="green")
frame_bottomleft = Frame(root, height=300, width=50, bg="blue")
frame_bottommiddle = Frame(root, height=300, width=250, bg="yellow")
frame_bottomright = Frame(root, height=300, width=250, bg="blue")
label_name=Label(frame_topmiddle, text="Name", font="halvetica")
label_phone=Label(frame_topmiddle, text="Phone", font="halvetica")
frame_topmiddle.grid(row=0, column=1)
frame_topleft.grid(row=0, column=0)
frame_topright.grid(row=0, column=2)
frame_bottomleft.grid(row=1, column=0)
frame_bottommiddle.grid(row=1, column=1)
frame_bottomright.grid(row=1, column=2)
label_name.grid(row=0, column=0)
root.mainloop()
So, I'm just wondering how I can fix this. I want the name label at the top left of the top middle frame.
The frame_topmiddle shrinks to the size of label_name and is, by default, displayed at the center of (row 0, column 1).
If you set the sticky option of the grid method to 'nw':
frame_topmiddle.grid(row=0, column=1, sticky='nw')
then frame_topmiddle will be in the top left corner of (row 0, column 1) instead of the center.
If you want frame_topmiddle to keep its initial size, you need to do
frame_topmiddle.grid_propagate(False).
Is it possible to get a text box to have a border even when inactive?
I am not sure I know what "border when inactive" means, but you can certainly add a border to a Text in TkInter. The following code creates two outer frames and two inner frames, then adds a Text to each inner frame. The frames are given a border of 5 px on all sides.
from Tkinter import *
root = Tk()
left_outer = Frame(root, bd=1)
left_outer.pack(side=LEFT, fill=Y, pady=5, padx=5)
right_outer = Frame(root, bd=1)
right_outer.pack(side=LEFT, fill=Y, pady=5, padx=5)
left = Frame(left_outer, bd=2, relief=SUNKEN)
right = Frame(right_outer, bd=2, relief=SUNKEN)
left.pack(fill=Y)
right.pack(fill=Y)
t_start = Text(left, width=20, height=200)
t_start.pack(side=LEFT, fill=Y)
s_start = Scrollbar(left)
s_start.pack(side=RIGHT, fill=Y)
s_start.config(command=t_start.yview)
t_start.config(yscrollcommand=s_start.set)
t_end = Text(right, width=20, height=200)
t_end.pack(side=LEFT, fill=Y)
s_end = Scrollbar(right)
s_end.pack(side=RIGHT, fill=Y)
s_end.config(command=t_end.yview)
t_end.config(yscrollcommand=s_end.set)
root.geometry("400x200")
root.mainloop()
odie5533's answer covers giving a border to a frame that contains only a Text object. This is a great way to give a 2D around a text object, but adds another widget in the mix. I think the original question was related to setting both the border width and relief type of the Text object. This snippet gives a relief to the Text object without involving another frame.
from Tkinter import *
root = Tk()
text_top = Text(root, relief=GROOVE, height=5, width = 40, borderwidth=2)
text_top.pack()
text_bottom = Text(root, relief=RIDGE, height=5, width = 40, borderwidth=2)
text_bottom.pack()
root.geometry("400x200")
root.mainloop()