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.
Related
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()
I have a layout with Frame and pack some widwets inside. This works so fare. But for the treeview widget it doesn't work and gives a strange error:
Display Names in the Treeview doesn't work with pack tkinter.TclError:
cannot use geometry manager pack inside . which already has slaves
managed by grid
Need help from experienced tkinter user.
Here my layout:
here, if I try the same with a treeview instead of a label widget:
here is my program:
import tkinter as tk
from tkinter import ttk
# Main App
win = tk.Tk()
win.title('Layout Test')
win.geometry('1200x720+300+300')
win.resizable(True, True)
# Frame Design
top_frame = tk.Frame(win, background="#FFF0C1", bd=1, relief="sunken")
left_frame = tk.Frame(win, background="#D2E2FB", bd=1, relief="sunken")
center_frame = tk.Frame(win, background="#CCE4CA", bd=1, relief="sunken")
right_frame = tk.Frame(win, background ='lightblue', bd=1, relief='sunken')
bottom_frame = tk.Frame(win, background="#F5C2C1", bd=1, relief="sunken")
top_frame.grid(row=0, column=0, columnspan=3, sticky="nsew", padx=2, pady=2)
left_frame.grid(row=1, column=0, sticky="nsew", padx=2, pady=2)
center_frame.grid(row=1, column=1, sticky="nsew", padx=2, pady=2)
right_frame.grid(row=1, column=2, sticky="nsew", padx=2, pady=2)
bottom_frame.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=2, pady=2)
win.grid_rowconfigure(0, weight=6)
win.grid_rowconfigure(1, weight=40)
win.grid_rowconfigure(3, weight=1)
win.grid_columnconfigure(0, weight=1)
win.grid_columnconfigure(1, weight=2)
win.grid_columnconfigure(2, weight=4)
# Display Names in the Treeview doesn't work with pack
# tkinter.TclError: cannot use geometry manager pack inside .
# which already has slaves managed by grid
treeview = ttk.Treeview(win)
treeview.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
treeview.insert('center_frame','0','item1', text = 'First item',tag='T' )
treeview.insert('center_frame','1','item2', text = 'Second item',tag='T' )
treeview.insert('center_frame','2','item3', text = 'Third item',tag='T' )
treeview.insert('center_frame','3','item4', text = 'Forth item',tag='T' )
treeview.insert('center_frame','end','item5', text = 'Five item',tag='T' )
treeview.insert('item1','end','item6', text = 'Sechster Text',tag='T' )
treeview.tag_configure('T', font=('Calibre', 15))
"""
# Test works well with pack
MyLabel = tk.Label(center_frame,text="Label inside Frame1")
MyLabel.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
"""
# Program here
# Status Bar at bottom_frame works well with pack
statustext = tk.StringVar()
statustext.set(' ... choose your avm_xml file') # will be changed from file dialoge
status = ttk.Label(bottom_frame, textvariable=statustext, borderwidth='25', relief=tk.SUNKEN, anchor=tk.W)
status.pack(side=tk.BOTTOM, fill=tk.X) #fill='both', expand=False, padx=8, pady=8
win.mainloop()
treeview has win as master, so when you try to pack it you get an error since you used grid for the other widgets in win. This is because the layout managers pack and grid cannot be used simultaneously in the same master widget.
On the other hand, your test label's master is center_frame, so you can pack it inside. If you change your treeview's master to center_frame, you will be able to pack it like the label.
import tkinter as tk
from tkinter import ttk
# Main App
win = tk.Tk()
win.title('Layout Test')
win.geometry('1200x720+300+300')
win.resizable(True, True)
# Frame Design
top_frame = tk.Frame(win, background="#FFF0C1", bd=1, relief="sunken")
left_frame = tk.Frame(win, background="#D2E2FB", bd=1, relief="sunken")
center_frame = tk.Frame(win, background="#CCE4CA", bd=1, relief="sunken")
right_frame = tk.Frame(win, background ='lightblue', bd=1, relief='sunken')
bottom_frame = tk.Frame(win, background="#F5C2C1", bd=1, relief="sunken")
top_frame.grid(row=0, column=0, columnspan=3, sticky="nsew", padx=2, pady=2)
left_frame.grid(row=1, column=0, sticky="nsew", padx=2, pady=2)
center_frame.grid(row=1, column=1, sticky="nsew", padx=2, pady=2)
right_frame.grid(row=1, column=2, sticky="nsew", padx=2, pady=2)
bottom_frame.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=2, pady=2)
win.grid_rowconfigure(0, weight=6)
win.grid_rowconfigure(1, weight=40)
win.grid_rowconfigure(3, weight=1)
win.grid_columnconfigure(0, weight=1)
win.grid_columnconfigure(1, weight=2)
win.grid_columnconfigure(2, weight=4)
treeview = ttk.Treeview(center_frame) # <-- changed master from win to center_frame
treeview.pack(side=tk.LEFT, fill=tk.BOTH, expand=1) # <-- pack works now
# Program here
# Status Bar at bottom_frame works well with pack
statustext = tk.StringVar()
statustext.set(' ... choose your avm_xml file') # will be changed from file dialoge
status = ttk.Label(bottom_frame, textvariable=statustext, borderwidth='25', relief=tk.SUNKEN, anchor=tk.W)
status.pack(side=tk.BOTTOM, fill=tk.X) #fill='both', expand=False, padx=8, pady=8
win.mainloop()
As far as I am concerned, if you change treeview.pack() to treeview.grid(sticky=W)etc it might work. You can't have both pack and grid in the same widget.
In the given code below, only when the "x" checkbox is checked, the "ChoosexFile" button should get enabled. Only when clicked upon the "ChoosexFile" button, the "file dialog box" must get opened. And the selected file contents must be displayed in the "Listbox" of the middle frame. The listbox of both middle frame & bottom frame must contain both "horizontal" & "vertical" scrollbar. And when clicked upon the "clear" button(top frame), the file contents being displayed in the "Listbox" of the middle frame must get cleared and the checkbox of it(either x or y) must get automatically unchecked. The same must get repeated for "y" checkbox(i.e the functionality must be same as "x"). And when clicked upon "reset" button of the middle frame, all the contents being displayed in the "listbox"(middle frame) must get cleared and also all the checkboxes must get unchecked automatically.
from tkinter import *
from tkinter import filedialog
def forButton1():
filename1 = filedialog.askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton2():
filename1 = filedialog.askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton7():
root.destroy()
root = Tk()
root.title("Spatialization of DSSAT")
root.grid_columnconfigure(0, weight=1)
topFrame = LabelFrame(root, text="Select input file")
topFrame.grid(row=0, column=0, padx=8, pady=8, sticky=N+E+S+W)
topFrame.grid_rowconfigure(0, weight=1)
topFrame.grid_rowconfigure(1, weight=1)
topFrame.grid_columnconfigure(0, weight=1)
topFrame.grid_columnconfigure(1, weight=1)
topFrame.grid_columnconfigure(2, weight=1)
middleFrame = LabelFrame(root, text="Input data")
middleFrame.grid(row=1, column=0, padx=8, pady=8, sticky=N+E+S+W)
middleFrame.grid_rowconfigure(0, weight=1)
middleFrame.grid_rowconfigure(1, weight=0)
middleFrame.grid_columnconfigure(0, weight=1)
middleFrame.grid_columnconfigure(1, weight=1)
bottomFrame = LabelFrame(root, text="Model Output")
bottomFrame.grid(row=2, column=0, padx=8, pady=8, sticky=N+E+S+W)
bottomFrame.grid_rowconfigure(0, weight=1)
bottomFrame.grid_columnconfigure(0, weight=1)
MyVar1 = IntVar()
MyVar2 = IntVar()
MyCheckbutton1 = Checkbutton(topFrame, text="x", variable=MyVar1)
MyCheckbutton1.grid(row=0, column=0, padx=4, pady=4)
Button1 = Button(topFrame, text="Choose xFile", command=forButton1)
Button1.grid(row=0, column=1, padx=4, pady=4)
Button3 = Button(topFrame, text="Clear")
Button3.grid(row=0, column=2, padx=4, pady=4)
MyCheckbutton2 = Checkbutton(topFrame, text="y", variable=MyVar2)
MyCheckbutton2.grid(row=1, column=0, padx=4, pady=4)
Button2 = Button(topFrame, text="Choose yFile", command=forButton2)
Button2.grid(row=1, column=1, padx=4, pady=4)
Button4 = Button(topFrame, text="Clear")
Button4.grid(row=1, column=2, padx=4, pady=4)
innerMiddleFrame = Frame(middleFrame)
innerMiddleFrame.grid(row=0, column=0, columnspan=2, padx=4, pady=4)
innerMiddleFrame.grid_columnconfigure(0, weight=1)
innerMiddleFrame.grid_columnconfigure(1, weight=0)
scrollbar = Scrollbar(innerMiddleFrame)
myList = Listbox(innerMiddleFrame, yscrollcommand=scrollbar.set)
myList.grid(row=0, column=0, sticky=N+E+S+W)
scrollbar.config(command=myList.yview)
scrollbar.grid(row=0, column=1, sticky=N+E+S+W)
Button5 = Button(middleFrame, text="Reset")
Button5.grid(row=1, column=0, padx=4, pady=4)
Button6 = Button(middleFrame, text="Submit")
Button6.grid(row=1, column=1, padx=4, pady=4)
innerBottomFrame = Frame(bottomFrame)
innerBottomFrame.grid(row=0, column=0, columnspan=2, padx=4, pady=4)
innerBottomFrame.grid_columnconfigure(0, weight=1)
innerBottomFrame.grid_columnconfigure(1, weight=0)
scrollbar = Scrollbar(innerBottomFrame)
myList = Listbox(innerBottomFrame, yscrollcommand=scrollbar.set)
myList.grid(row=0, column=0, sticky=N+E+S+W)
scrollbar.config(command=myList.yview)
scrollbar.grid(row=0, column=1, sticky=N+E+S+W)
Button7 = Button(bottomFrame, text="Exit", command=forButton7)
Button7.grid(row=6, column=0, padx=4, pady=4)
root.geometry("400x590")
root.mainloop()
Start out your buttons with a disabled state, and make a function to toggle their state by clicking the checkboxes.
Button1 = Button(topFrame, text="Choose xFile", command=forButton1, state="disabled")
Button2 = Button(topFrame, text="Choose yFile", command=forButton2, state="disabled")
...
def check_state(widget):
if widget["state"] == "normal":
widget["state"] = "disabled"
else:
widget["state"] = "normal"
MyCheckbutton1.config(command=lambda: check_state(Button1))
MyCheckbutton2.config(command=lambda: check_state(Button2))
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()
I am newbie in python tkinter,I want to have some 3 textbox of each having some 4 lines to print text on a single GUI.
I tried a code which creates just only one text box that wraps to the entire screen.i also wanted to number the 3 textboxes as 1,2,3 on its left side as label.Please help me to complete my code!
import tkinter as tki # Tkinter -> tkinter in Python3
class App(object):
def __init__(self):
self.root = tki.Tk()
# create a Frame for the Text and Scrollbar
txt_frm = tki.Frame(self.root, width=600, height=600)
txt_frm.pack(fill="both", expand=True)
# ensure a consistent GUI size
txt_frm.grid_propagate(False)
# implement stretchability
txt_frm.grid_rowconfigure(0, weight=1)
txt_frm.grid_columnconfigure(0, weight=1)
# create a Text widget
self.txt = tki.Text(txt_frm, borderwidth=3, relief="sunken")
self.txt.config(font=("consolas", 12), undo=True, wrap='word')
self.txt.grid(row=0, column=0, sticky="nsew", padx=2, pady=2)
# create a Scrollbar and associate it with txt
scrollb = tki.Scrollbar(txt_frm, command=self.txt.yview)
scrollb.grid(row=0, column=1, sticky='nsew')
self.txt['yscrollcommand'] = scrollb.set
app = App()
app.root.mainloop()
Try this
import tkinter as tki # Tkinter -> tkinter in Python3
class App(object):
def __init__(self,root):
self.root = root
# create a Frame for the Text and Scrollbar
txt_frm = tki.Frame(self.root, width=600, height=400)
txt_frm.pack(fill="both", expand=True)
# ensure a consistent GUI size
txt_frm.grid_propagate(False)
# create first Text label, widget and scrollbar
self.lbl1 = tki.Label(txt_frm, text="1")
self.lbl1.grid(row=0,column=0,padx=2,pady=2)
self.txt1 = tki.Text(txt_frm, borderwidth=3, relief="sunken", height=4,width=55)
self.txt1.config(font=("consolas", 12), undo=True, wrap='word')
self.txt1.grid(row=0, column=1, sticky="nsew", padx=2, pady=2)
scrollb1 = tki.Scrollbar(txt_frm, command=self.txt1.yview)
scrollb1.grid(row=0, column=2, sticky='nsew')
self.txt1['yscrollcommand'] = scrollb1.set
# create second Text label, widget and scrollbar
self.lbl2 = tki.Label(txt_frm, text="2")
self.lbl2.grid(row=1,column=0,padx=2,pady=2)
self.txt2 = tki.Text(txt_frm, borderwidth=3, relief="sunken",height=4,width=55)
self.txt2.config(font=("consolas", 12), undo=True, wrap='word')
self.txt2.grid(row=1, column=1, sticky="nsew", padx=2, pady=2)
scrollb2 = tki.Scrollbar(txt_frm, command=self.txt2.yview)
scrollb2.grid(row=1, column=2, sticky='nsew')
self.txt2['yscrollcommand'] = scrollb2.set
# create third Text label, widget and scrollbar
self.lbl3 = tki.Label(txt_frm, text="3")
self.lbl3.grid(row=2,column=0,padx=2,pady=2)
self.txt3 = tki.Text(txt_frm, borderwidth=3, relief="sunken",height=4,width=55)
self.txt3.config(font=("consolas", 12), undo=True, wrap='word')
self.txt3.grid(row=2, column=1, sticky="nsew", padx=2, pady=2)
scrollb3 = tki.Scrollbar(txt_frm, command=self.txt3.yview)
scrollb3.grid(row=2, column=2, sticky='nsew')
self.txt3['yscrollcommand'] = scrollb3.set
root = tki.Tk()
app = App(root)
root.mainloop()