Restrict Tkinter LabelFrame from changing proportions in a grid - python

I have created a GUI for reading a PDF file. As soon as I load PDF, the grid expands on x axis.
I have tried setting weights of row and column as 1, but I have no clue what else I am missing.
I want to restrict these 2 LabelFrame from resizing in wrong proportion, even if I resize the window, the proportions should be same.
In short, I want the two LabelFrame to be in equal space!
Does anyone have any idea how to achieve so?
My code
import cv2
from PIL.ImageTk import PhotoImage
from pdf2image import convert_from_path
from tkinter.ttk import Separator
from tkinter import Tk, LabelFrame, Label, Frame, Button
from tkinter.filedialog import askopenfilename
class GUI(Tk):
def __init__(self):
super().__init__()
self.geometry('1000x600')
# self.resizable(False, False)
self.init_frame()
def open_file(self):
file_path = askopenfilename(
title='Select a PDF...',
filetypes=(('PDF', '*.PDF'),))
h = self.pdf_frame.winfo_height()
w = self.pdf_frame.winfo_width()
print(h, w)
img = PhotoImage(convert_from_path(file_path, size=(w, h))[0])
self.pdf_frame.configure(image=img)
self.pdf_frame.image = img
def clear_file(self):
self.init_pdf_frame()
def init_frame(self):
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.frame = Frame(self)
self.frame.rowconfigure(0, weight=1)
self.frame.columnconfigure(0, weight=1)
self.frame.columnconfigure(1, weight=1)
self.frame.grid(column=0, row=0, sticky='news', padx=10, pady=10)
self.init_pdf_frame()
self.init_ocr_frame()
def init_pdf_frame(self):
image_viewer = LabelFrame(self.frame, text="PDF")
image_viewer.rowconfigure(2, weight=1)
image_viewer.columnconfigure(0, weight=1)
image_viewer.grid(column=0, row=0, sticky='news')
options = Frame(image_viewer)
options.columnconfigure(0, weight=1)
options.columnconfigure(1, weight=1)
options.grid(column=0, row=0, padx=5, pady=10, sticky='news')
open_button = Button(options, text='Open', command=self.open_file)
open_button.grid(column=0, row=0, padx=10, sticky='news')
clear_button = Button(options, text='Clear', command=self.clear_file)
clear_button.grid(column=1, row=0, padx=10, sticky='news')
line = Separator(image_viewer, orient='horizontal')
line.grid(row=1, column=0, sticky='ew')
self.pdf_frame = Label(image_viewer, text="PDF result appears here")
self.pdf_frame.grid(row=2, column=0, sticky='news')
def init_ocr_frame(self):
ocr_label = LabelFrame(self.frame, text="OCR")
ocr_label.rowconfigure(0, weight=1)
ocr_label.columnconfigure(0, weight=1)
ocr_label.grid(column=1, row=0, sticky='news')
label = Label(ocr_label, text="PDF result appears here")
label.grid(row=0, column=0, padx=10, pady=10, sticky='news')
if __name__ == '__main__':
GUI().mainloop()

Related

Sub Frame Is Not Expanded When Its Parent Is

import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
left_frame_1 = tk.Frame(root, background="#ff0000")
left_frame_1.grid(row=0, column=0)
left_frame_2 = tk.Frame(left_frame_1)
left_frame_2.grid(row=0, column=0)
left_label_1 = tk.Label(left_frame_2, text="HELLO")
left_label_2 = tk.Label(left_frame_2, text="WORLD")
left_label_3 = tk.Label(left_frame_2, text="=D")
left_label_1.grid(row=0, column=0)
left_label_2.grid(row=1, column=0)
left_label_3.grid(row=2, column=0)
right_frame1 = tk.Frame(root, background="#00ff00")
right_frame1.grid(row=0, column=1, sticky="nsew")
right_frame_2 = tk.Frame(right_frame1, background="#0000ff")
right_frame_2.grid(row=0, column=0)
right_label_1 = tk.Label(right_frame_2, text="CENTER ME!")
right_label_1.grid(row=0, column=0)
root.mainloop()
When my parent frame expands to all its free space, the child frame doesn't, instead it just stays on top.
I've been testing if .grid() has something to do with it, but haven't found anything.
Even if I add sticky="nsew" to both the frame and the label, there is still no change.
right_frame1 = tk.Frame(root, background="#00ff00")
right_frame1.grid(row=0, column=1, sticky="nsew")
right_frame_2 = tk.Frame(right_frame1, background="#0000ff")
right_frame_2.grid(row=0, column=0, sticky="nsew")
right_label_1 = tk.Label(right_frame_2, text="CENTER ME!")
right_label_1.grid(row=0, column=0, sticky="nsew")
My goal is for the parent frame (the one with the green color) to expand to all available space (which I've achieved), and for the child frame containing the label to expand.
right_frame_2 looks because it expands.
right_frame_1 is not visible because it is completely covered by right_frame_2.
I hope your help, thank you.
To get the result of the last image in the question, you need to:
change sticky options of .grid() for right_frame_2 and right_label_1
set weight options of .rowconfigure() and .columnconfigure() on root, right_frame1 and right_frame_2
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
left_frame_1 = tk.Frame(root, background="#ff0000")
left_frame_1.grid(row=0, column=0)
left_frame_2 = tk.Frame(left_frame_1)
left_frame_2.grid(row=0, column=0)
left_label_1 = tk.Label(left_frame_2, text="HELLO")
left_label_2 = tk.Label(left_frame_2, text="WORLD")
left_label_3 = tk.Label(left_frame_2, text="=D")
left_label_1.grid(row=0, column=0)
left_label_2.grid(row=1, column=0)
left_label_3.grid(row=2, column=0)
right_frame1 = tk.Frame(root, background="#00ff00")
right_frame1.grid(row=0, column=1, sticky="nsew")
right_frame_2 = tk.Frame(right_frame1, background="#0000ff")
right_frame_2.grid(row=0, column=0, sticky="nsew") # expand to fill available space
right_label_1 = tk.Label(right_frame_2, text="CENTER ME!")
right_label_1.grid(row=0, column=0, sticky="ew") # expand horizontally
root.rowconfigure(0, weight=1) # make left and right frame expand vertically
root.columnconfigure(1, weight=1) # make right frame expand horizontally
# allocate all space to right_frame_2
right_frame1.rowconfigure(0, weight=1)
right_frame1.columnconfigure(0, weight=1)
# allocate all space of right_frame_2 to right_label_1
right_frame_2.rowconfigure(0, weight=1)
right_frame_2.columnconfigure(0, weight=1)
root.mainloop()
Result:
When the window is resized:

Orient and Organize Tkinter frames

I would like to know how to create frames that align to grid and fill space I dictate. I am having a hard time grasping frame orientation within a window. I can make all the frames, but if I pack, they are all on left or in a line/on right. I played with that and decided on grid(). I set the window geometry and then use grid for frames. However, my frames all collapse down to the top left or my initial frame fills the whole space and the other two squeeze in around the edges. I tried using window geometry of 1024 and 768, then allotting width and height for my first frame to be 512 and 384. Then setting the next two to have width 512 and height of 192. I also saw in other articles that weight is important and tried iterations of code to alter that, but was unsuccessful. Rowspan and columnspan helped me get the background colors to appear so that I could visualize the space being occupied by each.
Anyway, code is below:
class twinsplay:
def __init__(self):
#Window
self.window = Tk()
self.window.geometry('1024x768')
self.window.grid_rowconfigure(1, weight=1)
self.window.grid_columnconfigure(1, weight=1)
#window title
self.window.title('Live Feed')
#frames and labels
self.frame_left = Frame(self.window, background='magenta')
self.frame_left.grid(row=0, column=0, padx=5, pady=5, rowspan=3, columnspan=3, sticky=NSEW)
self.label_left = Label(self.frame_left, text = 'Weather Data', justify=LEFT)
self.label_left.grid(row=0,column=0, sticky=NSEW)
self.frame_tr = Frame(self.window, background='green')
self.frame_tr.grid(row=0, column=3, padx=5, pady=5, rowspan=3, columnspan=2, sticky=NSEW)
self.label_tr = Label(self.frame_tr, text = 'Solar Data', justify = RIGHT)
self.label_tr.grid(row=0, column=512, sticky=NSEW)
self.frame_br = Frame(self.window, background='yellow')
self.frame_br.grid(padx=5, pady=5, rowspan=2, columnspan=2, sticky=NSEW)
self.label_br = Label(self.frame_br, text = 'News', justify = RIGHT)
self.label_br.grid(row=0, column=512, sticky=NSEW)
#main
self.window.mainloop()
```
I don't know if I understand your problem.
Your frames use full size inside window but elements inside frames are collapsed. You may need to use grid_rowconfigure/grid_columnconfigure also with frame_left, frame_tr, frame_br to resize elements in grid inside frames.
I move elements to rows an columns 0 because empty rows/columns have no size and there is no sense to put in column 512
from tkinter import *
class twinsplay:
def __init__(self):
self.window = Tk()
self.window.geometry('1024x768')
self.window.grid_rowconfigure(0, weight=1)
self.window.grid_columnconfigure(0, weight=1)
#window title
self.window.title('Live Feed')
#frames and labels
self.frame_left = Frame(self.window, background='magenta')
self.frame_left.grid(row=0, column=0, padx=5, pady=5, sticky=NSEW)
self.label_left = Label(self.frame_left, text = 'Weather Data', justify=LEFT, bg='red')
self.label_left.grid(row=0,column=0, sticky=NSEW)
self.frame_left.grid_rowconfigure(0, weight=1)
self.frame_left.grid_columnconfigure(0, weight=1)
# ---
self.frame_tr = Frame(self.window, background='green')
self.frame_tr.grid(row=0, column=1, padx=5, pady=5, sticky=NSEW)
self.label_tr = Label(self.frame_tr, text = 'Solar Data', justify = RIGHT, bg='green')
self.label_tr.grid(row=0, column=0, sticky=NSEW)
self.frame_tr.grid_rowconfigure(0, weight=1)
self.frame_tr.grid_columnconfigure(0, weight=1)
# ---
self.frame_br = Frame(self.window, background='yellow')
self.frame_br.grid(row=1, column=0, padx=5, pady=5, columnspan=2, sticky=NSEW)
self.label_br = Label(self.frame_br, text = 'News', justify = RIGHT, bg='yellow')
self.label_br.grid(row=0, column=0, sticky=NSEW)
self.frame_br.grid_rowconfigure(0, weight=1)
self.frame_br.grid_columnconfigure(0, weight=1)
#main
self.window.mainloop()
twinsplay()
But if you try to do something different then maybe you have to use grid_rowconfigure/grid_columnconfigure with other rows/columns - you can use it many times with different rows/columns.
EDIT:
from tkinter import *
class twinsplay:
def __init__(self):
self.window = Tk()
self.window.geometry('1024x768')
# left and right column will use the same size
self.window.grid_columnconfigure(0, weight=1)
self.window.grid_columnconfigure(1, weight=1)
# top and bottom rows will use the same size
self.window.grid_rowconfigure(0, weight=1)
self.window.grid_rowconfigure(1, weight=1)
#window title
self.window.title('Live Feed')
#frames and labels
# frame will use 2 rows
self.frame_left = Frame(self.window, background='magenta')
self.frame_left.grid(row=0, column=0, padx=5, pady=5, sticky=NSEW, rowspan=2)
self.label_left = Label(self.frame_left, text = 'Weather Data', justify=LEFT, bg='red')
self.label_left.grid(row=0,column=0, sticky=NSEW)
self.frame_left.grid_rowconfigure(0, weight=1)
self.frame_left.grid_columnconfigure(0, weight=1)
# ---
self.frame_tr = Frame(self.window, background='green')
self.frame_tr.grid(row=0, column=1, padx=5, pady=5, sticky=NSEW)
self.label_tr = Label(self.frame_tr, text = 'Solar Data', justify = RIGHT, bg='green')
self.label_tr.grid(row=0, column=0, sticky=NSEW)
self.frame_tr.grid_rowconfigure(0, weight=1)
self.frame_tr.grid_columnconfigure(0, weight=1)
# ---
self.frame_br = Frame(self.window, background='yellow')
self.frame_br.grid(row=1, column=1, padx=5, pady=5, columnspan=2, sticky=NSEW)
self.label_br = Label(self.frame_br, text = 'News', justify = RIGHT, bg='yellow')
self.label_br.grid(row=0, column=0, sticky=NSEW)
self.frame_br.grid_rowconfigure(0, weight=1)
self.frame_br.grid_columnconfigure(0, weight=1)
#main
self.window.mainloop()
twinsplay()

tkinter scrollable canvas after adding widgets with grid manager

I'm trying to create a canvas widget with a number of widgets embedded within it. Since there will frequently be too many widgets to fit in the vertical space I have for the canvas, it'll need to be scrollable.
import tkinter as tk # for general gui
import tkinter.ttk as ttk # for notebook (tabs)
class instructionGeneratorApp():
def __init__(self, master):
# create a frame for the canvas and scrollbar
domainFrame = tk.LabelFrame(master)
domainFrame.pack(fill=tk.BOTH, expand=1)
# make the canvas expand before the scrollbar
domainFrame.rowconfigure(0,weight=1)
domainFrame.columnconfigure(0,weight=1)
vertBar = ttk.Scrollbar(domainFrame)
vertBar.grid(row=0, column=1, sticky=tk.N + tk.S)
configGridCanvas = tk.Canvas(domainFrame,
bd=0,
yscrollcommand=vertBar.set)
configGridCanvas.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
vertBar.config(command=configGridCanvas.yview)
# add widgets to canvas
l = tk.Label(configGridCanvas, text='Products')
l.grid(row=1, column=0)
r = 2
for product in ['Product1','Product2','Product3','Product4','Product5','Product6','Product7','Product8','Product9','Product10','Product11','Product12','Product13','Product14','Product15','Product16','Product17','Product18','Product19','Product20']:
l = tk.Label(configGridCanvas, text=product)
l.grid(row=r, column=0)
c = tk.Checkbutton(configGridCanvas)
c.grid(row=r, column=1)
r += 1
ButtonFrame = tk.Frame(domainFrame)
ButtonFrame.grid(row=r, column=0)
removeServerButton = tk.Button(ButtonFrame, text='Remove server')
removeServerButton.grid(row=0, column=0)
# set scroll region to bounding box?
configGridCanvas.config(scrollregion=configGridCanvas.bbox(tk.ALL))
root = tk.Tk()
mainApp = instructionGeneratorApp(root)
root.mainloop()
As best as I can tell, I'm following the effbot pattern for canvas scrollbars, but I end up with either a scrollbar that isn't bound to the canvas, or a canvas that is extending beyond the edges of its master frame:
I've attempted the solutions on these questions, but there's still something I'm missing:
resizeable scrollable canvas with tkinter
Tkinter, canvas unable to scroll
Any idea what I'm doing wrong?
I have added some comments to #The Pinapple 's solution for future reference.
from tkinter import *
class ProductItem(Frame):
def __init__(self, master, message, **kwds):
Frame.__init__(self, master, **kwds)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.text = Label(self, text=message, anchor='w')
self.text.grid(row=0, column=0, sticky='nsew')
self.check = Checkbutton(self, anchor='w')
self.check.grid(row=0, column=1)
class ScrollableContainer(Frame):
def __init__(self, master, **kwargs):
#our scrollable container is a frame, this frame holds the canvas we draw our widgets on
Frame.__init__(self, master, **kwargs)
#grid and rowconfigure with weight 1 are used for the scrollablecontainer to utilize the full size it can get from its parent
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
#canvas and scrollbars are positioned inside the scrollablecontainer frame
#the scrollbars take a command parameter which is used to position our view on the canvas
self.canvas = Canvas(self, bd=0, highlightthickness=0)
self.hScroll = Scrollbar(self, orient='horizontal',
command=self.canvas.xview)
self.hScroll.grid(row=1, column=0, sticky='we')
self.vScroll = Scrollbar(self, orient='vertical',
command=self.canvas.yview)
self.vScroll.grid(row=0, column=1, sticky='ns')
self.canvas.grid(row=0, column=0, sticky='nsew')
#We do not only need a command to position but also one to scroll
self.canvas.configure(xscrollcommand=self.hScroll.set,
yscrollcommand=self.vScroll.set)
#This is the frame where the magic happens, all of our widgets that are needed to be scrollable will be positioned here
self.frame = Frame(self.canvas, bd=2)
self.frame.grid_columnconfigure(0, weight=1)
#A canvas itself is blank, we must tell the canvas to create a window with self.frame as content, anchor=nw means it will be positioned on the upper left corner
self.canvas.create_window(0, 0, window=self.frame, anchor='nw', tags='inner')
self.product_label = Label(self.frame, text='Products')
self.product_label.grid(row=0, column=0, sticky='nsew', padx=2, pady=2)
self.products = []
for i in range(1, 21):
item = ProductItem(self.frame, ('Product' + str(i)), bd=2)
item.grid(row=i, column=0, sticky='nsew', padx=2, pady=2)
self.products.append(item)
self.button_frame = Frame(self.frame)
self.button_frame.grid(row=21, column=0)
self.remove_server_button = Button(self.button_frame, text='Remove server')
self.remove_server_button.grid(row=0, column=0)
self.update_layout()
#If the widgets inside the canvas / the canvas itself change size,
#the <Configure> event is fired which passes its new width and height to the corresponding callback
self.canvas.bind('<Configure>', self.on_configure)
def update_layout(self):
#All pending events, callbacks, etc. are processed in a non-blocking manner
self.frame.update_idletasks()
#We reconfigure the canvas' scrollregion to fit all of its widgets
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
#reset the scroll
self.canvas.yview('moveto', '1.0')
#fit the frame to the size of its inner widgets (grid_size)
self.size = self.frame.grid_size()
def on_configure(self, event):
w, h = event.width, event.height
natural = self.frame.winfo_reqwidth() #natural width of the inner frame
#If the canvas changes size, we fit the inner frame to its size
self.canvas.itemconfigure('inner', width=w if w > natural else natural)
#dont forget to fit the scrollregion, otherwise the scrollbar might behave strange
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
if __name__ == "__main__":
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
sc = ScrollableContainer(root, bd=2)
sc.grid(row=0, column=0, sticky='nsew')
root.mainloop()
From what I can tell you are looking for something like this..
from tkinter import *
class ProductItem(Frame):
def __init__(self, master, message, **kwds):
Frame.__init__(self, master, **kwds)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.text = Label(self, text=message, anchor='w')
self.text.grid(row=0, column=0, sticky='nsew')
self.check = Checkbutton(self, anchor='w')
self.check.grid(row=0, column=1)
class ScrollableContainer(Frame):
def __init__(self, master, **kwargs):
Frame.__init__(self, master, **kwargs) # holds canvas & scrollbars
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = Canvas(self, bd=0, highlightthickness=0)
self.hScroll = Scrollbar(self, orient='horizontal',
command=self.canvas.xview)
self.hScroll.grid(row=1, column=0, sticky='we')
self.vScroll = Scrollbar(self, orient='vertical',
command=self.canvas.yview)
self.vScroll.grid(row=0, column=1, sticky='ns')
self.canvas.grid(row=0, column=0, sticky='nsew')
self.canvas.configure(xscrollcommand=self.hScroll.set,
yscrollcommand=self.vScroll.set)
self.frame = Frame(self.canvas, bd=2)
self.frame.grid_columnconfigure(0, weight=1)
self.canvas.create_window(0, 0, window=self.frame, anchor='nw', tags='inner')
self.product_label = Label(self.frame, text='Products')
self.product_label.grid(row=0, column=0, sticky='nsew', padx=2, pady=2)
self.products = []
for i in range(1, 21):
item = ProductItem(self.frame, ('Product' + str(i)), bd=2)
item.grid(row=i, column=0, sticky='nsew', padx=2, pady=2)
self.products.append(item)
self.button_frame = Frame(self.frame)
self.button_frame.grid(row=21, column=0)
self.remove_server_button = Button(self.button_frame, text='Remove server')
self.remove_server_button.grid(row=0, column=0)
self.update_layout()
self.canvas.bind('<Configure>', self.on_configure)
def update_layout(self):
self.frame.update_idletasks()
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
self.canvas.yview('moveto', '1.0')
self.size = self.frame.grid_size()
def on_configure(self, event):
w, h = event.width, event.height
natural = self.frame.winfo_reqwidth()
self.canvas.itemconfigure('inner', width=w if w > natural else natural)
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
if __name__ == "__main__":
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
sc = ScrollableContainer(root, bd=2)
sc.grid(row=0, column=0, sticky='nsew')
root.mainloop()

tkinter making frame sticky with window

I am new to this so not sure where I am going wrong here. I want to make my Frame_1 stick to the four corners of the window as you drag it out from the bottom right hand corner.
from tkinter import *
from tkinter import scrolledtext
from tkinter import ttk
window = Tk()
window.title("My Program")
tab_control = ttk.Notebook(window)
tab1 = ttk.Frame(tab_control)
tab1.grid(row=0, column=0)
tab2 = ttk.Frame(tab_control)
tab2.grid(row=0, column=0)
tab_control.grid(row=0, column=0, sticky=NSEW)
tab_control.add(tab1, text='First')
tab_control.add(tab2, text='Second')
labe1frame_1 = LabelFrame(tab1, text="Frame_1")
labe1frame_1.grid(row=0, column=0, padx=10, pady=10, sticky=NSEW)
txtbox = scrolledtext.ScrolledText(labe1frame_1, width=40, height=10)
txtbox.grid(row=0, column=0)
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
labe1frame_1.rowconfigure(0, weight=1)
labe1frame_1.columnconfigure(0, weight=1)
window.mainloop()
In your current GUI set up, using pack throughout may be a better idea:
import tkinter as tk
from tkinter import scrolledtext
from tkinter import ttk
if __name__ == '__main__':
window = tk.Tk()
window.title("My Program")
tab_control = ttk.Notebook(window)
tab1 = tk.Frame(tab_control)
tab1.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
tab2 = tk.Frame(tab_control)
tab2.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
tab_control.pack(fill=tk.BOTH, expand=True)
tab_control.add(tab1, text='First')
tab_control.add(tab2, text='Second')
labe1frame_1 = tk.LabelFrame(tab1, text="Frame_1")
labe1frame_1.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
txtbox = scrolledtext.ScrolledText(labe1frame_1, width=40, height=10)
txtbox.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
window.mainloop()
You can pack your Labeframe and scrolledText with this command to achieve that pack(expand=True, fil=BOTH) by removing the grid geometry layout manager.
from tkinter import *
from tkinter import scrolledtext
from tkinter import ttk
window = Tk()
window.title("My Program")
tab_control = ttk.Notebook(window)
tab1 = ttk.Frame(tab_control)
tab1.grid(row=0, column=0)
tab2 = ttk.Frame(tab_control)
tab2.grid(row=0, column=0, sticky=NSEW)
tab_control.grid(row=0, column=0, columnspan=3, padx=10, pady=10, sticky=E+W+N+S)
tab_control.add(tab1, text='First')
tab_control.add(tab2, text='Second')
labe1frame_1 = LabelFrame(tab1, text="Frame_1")
labe1frame_1.pack(expand=True, fil=BOTH)
txtbox = scrolledtext.ScrolledText(labe1frame_1, width=40, height=10)
txtbox.pack(expand=True, fil=BOTH)
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
labe1frame_1.rowconfigure(0, weight=1)
labe1frame_1.columnconfigure(0, weight=1)
window.mainloop()
You can allow your textbox and Frame 1 to expand by adding a weight to tab1 and a sticky to textbox.
When using grid() you will want to use columnconfig() and rowconfig() to provide weights to that frame so it can expand with the window resizing.
For the textbox to expand with the frame you will need to add the sticky argument also like this:
txtbox.grid(row=0, column=0, sticky="nswe")
See below code.
from tkinter import *
from tkinter import scrolledtext
from tkinter import ttk
window = Tk()
window.title("My Program")
tab_control = ttk.Notebook(window)
tab1 = ttk.Frame(tab_control)
tab1.grid(row=0, column=0)
tab1.columnconfigure(0, weight=1) # added weight
tab1.rowconfigure(0, weight=1) # added weight
tab2 = ttk.Frame(tab_control)
tab2.grid(row=0, column=0)
tab_control.grid(row=0, column=0, sticky="nswe")
tab_control.add(tab1, text='First')
tab_control.add(tab2, text='Second')
labe1frame_1 = LabelFrame(tab1, text="Frame_1")
labe1frame_1.grid(row=0, column=0, padx=10, pady=10, sticky="nswe")
txtbox = scrolledtext.ScrolledText(labe1frame_1, width=40, height=10)
txtbox.grid(row=0, column=0, sticky="nswe") # added sticky
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
labe1frame_1.rowconfigure(0, weight=1)
labe1frame_1.columnconfigure(0, weight=1)
window.mainloop()
The width of a grid column inside a given widget will be equal to the width of its widest cell, and the height of a grid row will be the height of its tallest cell. The sticky attribute on a widget controls only where it will be placed if it doesn't completely fill the cell.
from tkinter import *
from tkinter import scrolledtext
from tkinter import ttk
window = Tk()
window.title("My Program")
tab_control = ttk.Notebook(window)
tab1 = ttk.Frame(tab_control)
tab1.grid(row=0, column=0, sticky=NSEW) #add sticky option
tab2 = ttk.Frame(tab_control)
tab2.grid(row=0, column=0)
tab_control.grid(row=0, column=0, sticky=NSEW)
tab_control.add(tab1, text='First')
tab_control.add(tab2, text='Second')
labe1frame_1 = LabelFrame(tab1, text="Frame_1")
labe1frame_1.grid(row=0, column=0, padx=10, pady=10, sticky=NSEW)
txtbox = scrolledtext.ScrolledText(labe1frame_1, width=40, height=10)
txtbox.grid(row=0, column=0, sticky=NSEW) #add sticky option
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
labe1frame_1.rowconfigure(0, weight=1)
labe1frame_1.columnconfigure(0, weight=1)
#configure the row and column size of parent window
tab1.columnconfigure(0,weight=3)
tab1.rowconfigure(0,weight=3)
window.mainloop()

Making a child window open on top

I have a child window (root) in Tkinter. When i open the new window for import data and processing, this child window go under the main window.
I used
root.lift()
root.call('wm', 'attributes', '.', '-topmost', True)
but the child window remain in the top always, also when a directory window is open
from __future__ import division
from Tkinter import *
from math import pi
import tkMessageBox
import Tkinter, Tkconstants, tkFileDialog
from numpy import nan
import Tkinter as tk
import os, shutil
class MainWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.filename = None
self.master.title("input")
self.master.minsize(250, 150)
self.grid(sticky=E+W+N+S)
top=self.winfo_toplevel()
top.rowconfigure(0, weight=1)
top.columnconfigure(0, weight=1)
for i in range(1): self.rowconfigure(i, weight=1)
self.columnconfigure(1, weight=1)
self.button0 = Button(self, text="start", command=self.open_new_window, activeforeground="red")
self.button0.grid(row=0, column=1, pady=2, padx=2, sticky=E+W+N+S)
def open_new_window(self):
root = tk.Toplevel(self)
root.title("process")
root.minsize(400, 150)
root.maxsize(400, 150)
root.grid()
top = root.winfo_toplevel()
top.rowconfigure(0, weight=1)
top.columnconfigure(0, weight=1)
root.CHART_FILE_TYPES = [('All files', '*'),('text file', '.txt')]
for i in range(5): root.rowconfigure(i, weight=1)
root.columnconfigure(1, weight=1)
root.CheckVar_a = IntVar()
root.check_a = tk.Checkbutton(root, text="A", variable=root.CheckVar_a, onvalue=0, offvalue=1)
root.check_a.grid(row=0, column=0, pady=0, padx=0, columnspan=3, sticky=W)
root.CheckVar_b = IntVar()
root.check_b = tk.Checkbutton(root, text="B", variable=root.CheckVar_b, onvalue=0, offvalue=1)
root.check_b.grid(row=1, column=0, pady=0, padx=0, columnspan=3, sticky=W)
root.CheckVar_c = IntVar()
root.check_c = tk.Checkbutton(root, text="C", variable=root.CheckVar_c, onvalue=0, offvalue=1)
root.check_c.grid(row=2, column=0, pady=0, padx=0, columnspan=3, sticky=W)
root.CheckVar_d = IntVar()
root.check_d = tk.Checkbutton(root, text="D", variable=root.CheckVar_d, onvalue=0, offvalue=1)
root.check_d.grid(row=3, column=0, pady=0, padx=0, columnspan=3, sticky=W)
def open_file():
root.filename = tkFileDialog.askopenfilename(filetypes=[("Text Files",'.txt')])
if not root.filename:
tkMessageBox.showerror("Error", message="No text file (*.txt) imported ")
return root.filename
open_txt = tk.Button(root, text="Open", command=open_file, activeforeground="red")
open_txt.grid(row=4, column=0, pady=2, padx=2, sticky=E+W+N+S)
def process():
if not root.filename:
tkMessageBox.showerror("Error", message="None file (*.txt) active to process")
return None
pass
pro = tk.Button(root, text="Process", command=process, activeforeground="red")
pro.grid(row=4, column=1, pady=2, padx=2, sticky=E+W+N+S)
if __name__=="__main__":
d = MainWindow()
d.mainloop()
You are using tkinter wrong. You can't have more than one instance of Tk in your program. You get one implicitly when you create a frame before creating the root window, then you get another in open_new_window.
To create a child window, create an instance of Toplevel.

Categories