Tkinter create a hidden frame - python

I'm creating a GUI whose window will consists of a few frames.
I need to pack many different widgets in each frame so if all are shown it will occupy a lot of space.
The idea is that each frame will be revealed/hidden with the push of a button.
I'm able to hide and reveal each frame using buttons, however I'd like those frame to start as hidden.
Is there a way to do that?
Here's a code that hides/reveals the frames.
import tkinter as tk
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
import os
# Method to make Label(Widget) invisible
def hide_frame(frame):
# This will remove the widget
frame.grid_remove()
# Method to make Label(widget) visible
def show_frame(frame):
# This will recover the widget
frame.grid()
#____________________________________________________________________________________________
#This will be the main window
window = tk.Tk()
window.geometry('500x500')
window.title("daq")
#____________________________________________________________________________________________
#Upper frame
frame_logo = Frame(window)
#____________________________________________________________________________________________
#Lower frame
frame_main = Frame(window)
frame_main.place(rely=0.10, relx=0.0, relwidth=1.0)
#Create a tabcontrol
tabControl = ttk.Notebook(frame_main)
tabControl.grid(column=0, row=1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Digitizer tab
tab_Digitizer = ttk.Frame(tabControl)
tabControl.add(tab_Digitizer, text=' Digitizer ')
digitizer_tab_dummy_label = Label(tab_Digitizer, text="")
digitizer_tab_dummy_label.grid(column=0, row=0)
#General board settings
lbl_general_board_registers = Label(tab_Digitizer,
text="General board registers",
font='bold')
lbl_general_board_registers.grid(column=0, row=1, sticky=W)
frame_general_board_registers = Frame(tab_Digitizer)
frame_general_board_registers.grid(column=0, row=2)
btn_hide_general_board_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_general_board_registers) )
btn_hide_general_board_registers.grid(column=1, row=1)
btn_show_general_board_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_general_board_registers))
btn_show_general_board_registers.grid(column=2, row=1)
lbl_threshold1 = Label(frame_general_board_registers, text="Threshold1")
lbl_threshold1.grid(column=1, row=0)
lbl_trigger1 = Label(frame_general_board_registers, text="Trigger1")
lbl_trigger1.grid(column=1, row=1)
#Channel settings
lbl_channel_registers = Label(tab_Digitizer,
text="Channel registers",
font='bold')
lbl_channel_registers.grid(column=0, row=3, sticky=W)
frame_channel_registers = Frame(tab_Digitizer)
frame_channel_registers.grid(column=0, row=4)
btn_hide_channel_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_channel_registers) )
btn_hide_channel_registers.grid(column=1, row=3)
btn_show_channel_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_channel_registers))
btn_show_channel_registers.grid(column=2, row=3)
lbl_threshold = Label(frame_channel_registers, text="Threshold")
lbl_threshold.grid(column=1, row=0)
lbl_trigger = Label(frame_channel_registers, text="Trigger")
lbl_trigger.grid(column=1, row=1)
#Misc settings
lbl_misc_registers = Label(tab_Digitizer,
text="Misc settings",
font='bold')
lbl_misc_registers.grid(column=0, row=5, sticky=W)
frame_misc_registers = Frame(tab_Digitizer)
frame_misc_registers.grid(column=0, row=6)
#_________________________________________________________________________________________________
tab_SignalViewer = ttk.Frame(tabControl)
tabControl.add(tab_SignalViewer, text=' Signal Viewer ')
#tabControl.grid(column=0, row=1)
#This keeps the window open - has to be at the end
window.mainloop()

Related

Python tkinter : how to resize widgets when i resize the screen

I'm beginner...
When the code below is executed, how do I make the widgets inside increase when the screen size is increased to width? but, it couldn't resized..
Does it matter if I use either pack or grid?
i can't solve it....
from tkinter import *
from tkinter import ttk
class program:
def __init__(self):
self.root = Tk()
self.root.title("Python")
self.root.resizable(True, True)
self.create_project()
def create_project(self):
Topic_Label = ttk.Label(self.root, text="program")
Topic_Label.pack(side="top")
Record_LabelFrame = LabelFrame(self.root, text="Record information")
Record_LabelFrame.pack(side="top", anchor=W, padx=10)
date = ttk.Label(Record_LabelFrame, text="date")
date.grid(column=0, row=0, sticky=W)
Topic_Label_Entry1 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry1.grid(column=0, row=1)
time = ttk.Label(Record_LabelFrame, text="time")
time.grid(column=1, row=0, sticky=W)
Topic_Label_Combo1 = ttk.Combobox(Record_LabelFrame)
Topic_Label_Combo1.grid(column=1, row=1)
recorder = ttk.Label(Record_LabelFrame, text="record")
recorder.grid(column=2, row=0, sticky=W)
Topic_Label_Entry2 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry2.grid(column=2, row=1)
loc = ttk.Label(Record_LabelFrame, text="location")
loc.grid(column=0, row=2, sticky="W")
RadioVar = IntVar()
Radio_Frame = Frame(Record_LabelFrame)
Radio_Frame.grid(column=0, row=3, sticky=W)
Topic_Label_Radio1 = ttk.Radiobutton(Radio_Frame, text="A", variable=RadioVar, value=1)
Topic_Label_Radio1.grid(column=0, row=0)
Topic_Label_Radio2 = ttk.Radiobutton(Radio_Frame, text="B", variable=RadioVar, value=2)
Topic_Label_Radio2.grid(column=1, row=0)
Topic_Label_Radio3 = ttk.Radiobutton(Radio_Frame, text="C", variable=RadioVar, value=3)
Topic_Label_Radio3.grid(column=2, row=0)
count = ttk.Label(Record_LabelFrame, text="count")
count.grid(column=1, row=2, sticky="W")
Topic_Label_Combo2 = ttk.Combobox(Record_LabelFrame)
Topic_Label_Combo2.grid(column=1, row=3)
seed_name = ttk.Label(Record_LabelFrame, text="seed")
seed_name.grid(column=2, row=2, sticky="W")
Topic_Label_Entry4 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry4.grid(column=2, row=3)
mt = program()
mt.root.mainloop()
I want to print like this that widget resize automatically when i resize the screen
https://i.stack.imgur.com/iSbaJ.png
https://i.stack.imgur.com/mzv9R.png

How to align widgets in Tkinter to center

I am working on a simple counter app in tkinter. I rigged up some code looking at few tutorial on web. All the functions of a counter are set up. But when it comes to the designing of the app, I want the Count, the Count button, and the reset button to be aligned at the center.
The code is as below
from tkinter import Label, Button, Tk
from tkinter import font
window = Tk()
window.geometry('500x500')
window.title("Counter")
window.count = 0
def increment():
window.count += 1
lbl.configure(text=window.count)
def reset():
window.count = 0
lbl.configure(text=window.count)
lbl = Label(window, text="0", font=("Apple Braille", 60))
lbl.grid(column=0, row=0)
btn1 = Button(window, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(window, text="Reset", command=reset)
btn2.grid(column=1, row=1)
btn1['font'] = btn2['font'] = font.Font(size=30)
window.mainloop()
A Screenshot of my counter app is here
Any help in this aspect will be appreciated.
Thanks,
It is easier to use pack() instead of grid() for your requirement.
lbl = Label(window, text="0", font=("Apple Braille", 60))
lbl.pack()
# frame for the two buttons
frame = Frame(window)
frame.pack()
btn1 = Button(frame, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(frame, text="Reset", command=reset)
btn2.grid(column=1, row=1)
If you want to put at the center of the window:
# frame for the label and buttons
frame = Frame(window)
frame.place(relx=0.5, rely=0.5, anchor="c") # put at center of window
lbl = Label(frame, text="0", font=("Apple Braille", 60))
lbl.grid(row=0, column=0, columnspan=2)
btn1 = Button(frame, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(frame, text="Reset", command=reset)
btn2.grid(column=1, row=1)

Make scrollable canvas expand based on the embedded frame

I'm creating a frame which has many that are build vertically and I need a scrollbar to make them all visible. To do that I embedded my frame on a canvas.
The problem is that the widgets on the frame require more width that what the canvas provides as shown below
If I don't embed the frame on a canvas, then the widgets take the proper amount of width and are resized properly. I believe that the problem is the the canvas spans across 1 column whereas the widgets in the canvas require more than 2. I used `columnspan=2' on the canvas but the widgets on the embedded frame are still cut; they are just zoomed.
Is there a way to expand the width of the canvas according to the width they frame wants?
Here's an example code
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from PIL import ImageTk, Image
import os
# Method to make Label(Widget) invisible
def hide_frame(frame):
# This will remove the widget
frame.grid_remove()
# Method to make Label(widget) visible
def show_frame(frame, c, r):
# This will recover the widget
frame.grid(column=c, row=r)
def populate(frame):
'''Put in some fake data'''
for row in range(100):
tk.Label(frame, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0)
t="Blah blah blah blah blah blah blah blah %s" %row
tk.Label(frame, text=t).grid(row=row+4, column=1)
#____________________________________________________________________________________________
#This will be the main window
window = tk.Tk()
#window.geometry('1500x1200')
window.attributes('-zoomed', True)
window.title("daq")
frame_main = Frame(window)
frame_main.place(rely=0.10, relx=0.0, relwidth=1.0)
#Create a tabcontrol
tabControl = ttk.Notebook(frame_main)
tabControl.grid(column=0, row=1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Digitizer tab
tab_Digitizer = ttk.Frame(tabControl)
tabControl.add(tab_Digitizer, text=' Digitizer ')
digitizer_tab_dummy_label = Label(tab_Digitizer, text="")
digitizer_tab_dummy_label.grid(column=0, row=0)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Channel settings
lbl_channel_registers = Label(tab_Digitizer, text="Channel registers", font='bold')
lbl_channel_registers.grid(column=0, row=3, sticky=W)
frame_channel_registers = Frame(tab_Digitizer)
frame_channel_registers.grid(column=0, row=4)
btn_hide_channel_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_channel_registers) )
btn_hide_channel_registers.grid(column=1, row=3)
btn_show_channel_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_channel_registers, 0, 4))
btn_show_channel_registers.grid(column=2, row=3)
##Channel settings - PSD
def onFrameConfigure(event):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))
def handle_user_scrolling(event):
canvas.yview_scroll(int(-event.delta/abs(event.delta)), "units")
def handle_scrollbar_scrolling(event):
canvas.configure(scrollregion=canvas.bbox("all"))
lbl_PSD_channel_registers = Label(frame_channel_registers, text="DPP-PSD registers")
lbl_PSD_channel_registers.grid(column=0, row=3, padx=5, sticky=W)
btn_hide_PSD_channel_registers = Button(frame_channel_registers, text="Hide", fg="red", command=lambda: [hide_frame(canvas), hide_frame(myscrollbar)] )
btn_hide_PSD_channel_registers.grid(column=1, row=3)
btn_show_PSD_channel_registers = Button(frame_channel_registers, text="Show", fg="green", command=lambda: [show_frame(canvas, 0, 4), show_frame(myscrollbar, 1, 4)])
btn_show_PSD_channel_registers.grid(column=2, row=3)
canvas = tk.Canvas(frame_channel_registers, borderwidth=1, background="#FF0000")
frame_PSD_channel_registers = Frame(canvas, background="#0000FF")
frame_PSD_channel_registers.grid(column=0, row=0, padx=25, sticky=W)
frame_PSD_channel_registers.bind("<MouseWheel>", handle_user_scrolling)
frame_PSD_channel_registers.bind("<Configure>", handle_scrollbar_scrolling)
myscrollbar=Scrollbar(frame_channel_registers ,orient="vertical", command=canvas.yview)
#canvas.configure(yscrollcommand=myscrollbar.set)
canvas.configure(scrollregion=canvas.bbox("all"))
myscrollbar.grid(column=1, row=4, sticky=NS)
canvas.grid(column=0, row=4, columnspan=3)
#frame_PSD_channel_registers = Frame(canvas, background="#0000FF")
#frame_PSD_channel_registers.grid(column=0, row=0, padx=25, sticky=W)
#frame_PSD_channel_registers.bind("<MouseWheel>", handle_user_scrolling)
#frame_PSD_channel_registers.bind("<Configure>", handle_scrollbar_scrolling)
canvas.create_window((0, 0), window=frame_PSD_channel_registers, anchor="nw")
canvas.configure(yscrollcommand=myscrollbar.set)
###### PSD channels settings
#Short gate
def short_gate_width_selection(event):
print ("Short gate width : " + str( entry_short_gate_width.get() ) + " " + var_short_gate_width_unit.get() )
pass
lbl_short_gate_width = Label(frame_PSD_channel_registers, text="Short gate width")
lbl_short_gate_width.grid(column=0, row=0, padx=25, sticky=W)
var_short_gate_width = IntVar(frame_PSD_channel_registers)
var_short_gate_width.set("15")
entry_short_gate_width = Entry(frame_PSD_channel_registers, width=10, textvariable=var_short_gate_width, exportselection=0)
entry_short_gate_width.grid(column=1, row=0, sticky=W)
opt_short_gate_width = ["samples", "ns"]
var_short_gate_width_unit = StringVar(frame_PSD_channel_registers)
var_short_gate_width_unit.set(opt_short_gate_width[0]) # default value
short_gate_width_unit = OptionMenu(frame_PSD_channel_registers, var_short_gate_width_unit, *opt_short_gate_width, command = short_gate_width_selection)
entry_short_gate_width.bind('<Return>', short_gate_width_selection)
short_gate_width_unit.grid(column=2, row=0, sticky=W)
#Long gate
def long_gate_width_selection(event):
print ("Long gate width : " + str( entry_long_gate_width.get() ) + " " + var_long_gate_width_unit.get() )
pass
lbl_long_gate_width = Label(frame_PSD_channel_registers, text="Long gate width")
lbl_long_gate_width.grid(column=0, row=1, padx=25, sticky=W)
var_long_gate_width = IntVar(frame_PSD_channel_registers)
var_long_gate_width.set("100")
entry_long_gate_width = Entry(frame_PSD_channel_registers, width=10, textvariable=var_long_gate_width, exportselection=0)
entry_long_gate_width.grid(column=1, row=1, sticky=W)
opt_long_gate_width = ["samples", "ns"]
var_long_gate_width_unit = StringVar(frame_PSD_channel_registers)
var_long_gate_width_unit.set(opt_long_gate_width[0]) # default value
long_gate_width_unit = OptionMenu(frame_PSD_channel_registers, var_long_gate_width_unit, *opt_long_gate_width, command = long_gate_width_selection)
entry_long_gate_width.bind('<Return>', long_gate_width_selection)
long_gate_width_unit.grid(column=2, row=1, sticky=W)
#Extras word options
def extras_word_options_selection(event):
if 'Counter' in var_extras_word_options_selection.get():
extras_word_options_step_counter.grid(column=2, row=22, sticky=W)
else:
extras_word_options_step_counter.grid_remove()
print ("Extras word options : " + var_extras_word_options_selection.get() )
pass
def extras_word_options_step_counter_selection(event):
print ("Step for trigger counter : ", var_extras_word_options_step_counter.get() )
pass
lbl_extras_word_options_selection = Label(frame_PSD_channel_registers, text="Extras word options")
lbl_extras_word_options_selection.grid(column=0, row=22, padx=25, sticky=W)
opt_extras_word_options_selection = ["[31:16] = Extended Time Stamp , [15:0] = Baseline * 4",
"[31:16] = Extended Time Stamp , [15:0] = Flags",
"[31:16] = Extended Time Stamp , [15:10] = Flags, [9:0] = Fine Time Stamp",
"[31:16] = Lost Trigger Counter , [15:0] = Total Trigger Counter",
"[31:16] = Positive Zero Crossing, [15:0] = Negative Zero Crossing",
"Fixed value = 0x12345678 (debug use only)."]
var_extras_word_options_selection = StringVar(frame_PSD_channel_registers)
var_extras_word_options_selection.set(opt_extras_word_options_selection[2]) # default value
extras_word_options_selection = OptionMenu(frame_PSD_channel_registers, var_extras_word_options_selection, *opt_extras_word_options_selection, command = extras_word_options_selection)
extras_word_options_selection.grid(column=1, row=22, sticky=W)
#This keeps the window open - has to be at the end
window.mainloop()

How to add multiline text dynamically in tkinter python?

I have created a chat application, in which i use ListBox for showing the chat history. It looks good until I enter a long sting which goes beyond the screen. Is there a way to break the string and show in new line or any other way to show the complete string. I'm new to Tkinter and im not aware of many widgets available.
Here is my sample code
from tkinter import *
class Actions:
def chatUpdate(chat):
chatlist.insert(Actions.chatLast,chat)
Actions.chatLast=Actions.chatLast+1
chatlist.pack( side=LEFT, fill=BOTH)
chatBox.config(command=chatlist.yview)
def callUpdater():
txt=textBox.get()
text_text.set("")
Actions.chatUpdate(txt)
root = Tk()
root.title("Chat App")
frame1 = Frame(root, bd=4)
frame1.pack(side=TOP)
frame2 = Frame(root, bd=4)
frame2.pack(side=TOP)
frame3 = Frame(root, bd=4)
frame3.pack(side=TOP)
# chat box
chatBox = Scrollbar(frame1)
chatBox.pack(side=RIGHT, fill=Y)
chatlist = Listbox(frame1, yscrollcommand = chatBox.set, width=50)
Actions.chatLast=0
Actions.chatUpdate(" ")
# text box
textView = Label(frame2, text="Input: ")
textView.pack(side=LEFT)
text_text = StringVar()
textBox = Entry(frame2, textvariable=text_text, bd=0, width=40, bg="pink")
textBox.pack(side=RIGHT)
# send button
button = Button(frame3, text="Send", fg="black", command=callUpdater)
button.pack(side=TOP)
root.mainloop()
You can replace the Listbox by a Text widget in 'disabled' mode which automatically wraps long lines. You will just need to put the widget back in 'normal' mode each time you insert text:
from tkinter import *
def callUpdater():
text = textBox.get()
textBox.delete(0, 'end')
chat.configure(state='normal')
chat.insert('end', text + '\n')
chat.configure(state='disabled')
root = Tk()
chatBox = Scrollbar(root)
chat = Text(root, wrap='word', state='disabled', width=50,
yscrollcommand=chatBox.set)
chatBox.configure(command=chat.yview)
chat.grid(row=0, columnspan=2, sticky='ewns')
chatBox.grid(row=0, column=2, sticky='ns')
Label(root, text="Input: ").grid(row=1, column=0)
textBox = Entry(root, bd=0, width=40, bg="pink")
textBox.grid(row=1, column=1)
Button(root, text="Send", command=callUpdater).grid(row=2, columnspan=2)
root.mainloop()
By the way, both the Listbox and Text widgets support the index 'end' so you don't have to keep track of how many lines you have inserted.

More than one text box on a gui

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()

Categories