Tkinter Scrollbar Not Showing in Second Frame - python

I am trying to resolve an error in which I create a second frame within Tkinter with a group of labels and entry boxes and I'm trying to implement a scrollbar for future use when I place many more labels and boxes but for some reason only the frame, boxes, and labels pop up - but no scrollbar. Here is the code so far:
from tkinter import *
from tkinter import ttk
win = Tk()
# Creating Frames
wrapper1 = LabelFrame(win, width = 1500, height = 1000)
wrapper2 = LabelFrame(win, width = 1500, height = 1000)
mycanvas = Canvas(wrapper1)
mycanvas.pack(side = LEFT, fill = "both", expand ="yes")
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window = myframe, anchor = "nw")
wrapper1.pack(fill = "both", expand = "yes", padx = 10, pady = 10)
# Creating a Hide Frame Function
def hide_menu_frames():
# Destroying the children widgets in each frame
for widget in wrapper1.winfo_children():
widget.destroy()
for widget in wrapper2.winfo_children():
widget.destroy()
# Hiding all frames
wrapper1.pack_forget()
wrapper2.pack_forget()
def home():
#hide_menu_frames()
myframe.pack(fill = "both", expand = 1)
start_label = Label(myframe, text = "Choose Length of Loan Model", font = ("Helvetica", 18)).pack(pady = 100)
#start_label.grid(row = 0, column = 1, pady = 50)
# Creating Buttons
home_button1 = Button(myframe, text = "12 Month Model", bg='#ffffff', activeforeground='#4444ff', font = ("Helvetica", 15, BOLD), command = second_home).pack(pady = 10)
def second_home():
hide_menu_frames()
second_label = Label(wrapper2, text = "Please Input Loan Parameters", font = ("Helvetica", 18), pady = 10).pack()
# Creating Input Box for Original Balance Month 1
global og_bal_input
og_bal_input = Entry(wrapper2)
og_bal_input.pack()
# Creating Label for Original Balance Month 1
global og_bal_label
og_bal_label = Label(wrapper2, text = "Enter Original Balance for Month 1")
og_bal_label.pack()
# Creating Input Box for Original Balance Month 2
global og_bal_input2
og_bal_input2 = Entry(wrapper2)
og_bal_input2.pack()
# Creating Label for Original Balance Month 2
global og_bal_label2
og_bal_label2 = Label(wrapper2, text = "Enter Original Balance for Month 2")
og_bal_label2.pack()
# Creating Input Box for Original Balance Month 3
global og_bal_input3
og_bal_input3 = Entry(wrapper2)
og_bal_input3.pack()
# Creating Label for Original Balance Month 3
global og_bal_label3
og_bal_label3 = Label(wrapper2, text = "Enter Original Balance for Month 3")
og_bal_label3.pack()
mycanvas = Canvas(wrapper2)
mycanvas.pack(side = LEFT, fill = "both", expand ="yes")
yscrollbar = ttk.Scrollbar(wrapper2, orient = VERTICAL, command = mycanvas.yview)
yscrollbar.pack(side = RIGHT, fill = "y")
mycanvas.configure(yscrollcommand = yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion = mycanvas.bbox('all')))
wrapper2.pack(fill = "both", expand = "yes", padx = 10, pady = 10)
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window = myframe, anchor = "nw")
Everything works until I press the first button to get to the 'second home' - I can see the input boxes and labels but no scrollbar

You haven't put the entries and labels inside myframe so they won't be in the scrolled canvas. You need to rearrange your code so the canvas (mycanvas) and its frame (myframe) are created first, then make the entries and labels children of the frame in the canvas (myframe). I've added a loop which demonstrates the scrolling, you can remove this.
def second_home():
hide_menu_frames()
mycanvas = Canvas(wrapper2)
mycanvas.pack(side = LEFT, fill = "both", expand ="yes")
yscrollbar = ttk.Scrollbar(wrapper2, orient = VERTICAL, command = mycanvas.yview)
yscrollbar.pack(side = RIGHT, fill = "y")
mycanvas.configure(yscrollcommand = yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion = mycanvas.bbox('all')))
wrapper2.pack(fill = "both", expand = "yes", padx = 10, pady = 10)
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window = myframe, anchor = "nw")
second_label = Label(myframe, text = "Please Input Loan Parameters", font = ("Helvetica", 18), pady = 10).pack()
# Creating Input Box for Original Balance Month 1
global og_bal_input
og_bal_input = Entry(myframe)
og_bal_input.pack()
# Creating Label for Original Balance Month 1
global og_bal_label
og_bal_label = Label(myframe, text = "Enter Original Balance for Month 1")
og_bal_label.pack()
# Creating Input Box for Original Balance Month 2
global og_bal_input2
og_bal_input2 = Entry(myframe)
og_bal_input2.pack()
# Creating Label for Original Balance Month 2
global og_bal_label2
og_bal_label2 = Label(myframe, text = "Enter Original Balance for Month 2")
og_bal_label2.pack()
# Creating Input Box for Original Balance Month 3
global og_bal_input3
og_bal_input3 = Entry(myframe)
og_bal_input3.pack()
# Creating Label for Original Balance Month 3
global og_bal_label3
og_bal_label3 = Label(myframe, text = "Enter Original Balance for Month 3")
og_bal_label3.pack()
for i in range(100):
Label(myframe, text = "test scroll " + str(i)).pack()

Related

hrizontal scrol bar to a treeview+tkinter

I want to add a horizontal scroll bar to the particular tree-view table since I have not used Tkinter before so please help!
import tkinter
def __create_tree_view(self):
""" Creates a TreeView Layout with req Headers """
style = it.Style()
style.configure("Custom.Treeview.Heading",foreground="green", relief="flat")
style.map("Custom.Treeview.Heading", relief=[('active','groove'),('pressed','sunken')])
style.configure('Treeview', rowheight=20)
#
self.tree_view = ttk.Treeview(self.right_frame, selectmode ='browse',\
style="Custom.Treeview")
self.tree_view.grid(row=1, column=1, sticky=tk.NSEW)
self.verticalscrollba = ttk.Scrollbar(self.right_frame, orient="vertical", \
command=self.tree_view.view)
self. verticalscrollbar.grid(row=1,column=1,sticky='nse')
self.tree_view.configure(yscrollcommand = self.verscrlbar.set)
# Defining number of columns
self.tree_view["columns"] = ("1", "2", "3", "4")
# Defining heading
self.tree_view['show'] = 'headings'
# Assigning the width and anchor to the respective columns
self.tree_view.column("1", width = int(self.window_width/5), anchor ='ca, stretch=False)
self.tree_view.column("2", width = int(self.window_width/4)-30, anchor ='ca, stretch=False)
self.tree_view.column("3", width = int(self.window_width/6)-30, anchor ='ca, stretch=False)
self.tree_view.column("4", width = int(self.window_width/3), anchor ='ca, stretch=False)
# Assigning the heading names to the respective columns
self.tree_view.heading("1", text ="Brand/Model/Type")
self.tree_view.heading("2", text ="Device_Id")
self.tree_view.heading("3", text ="Device_Ip")
self.tree_view.heading("4", text ="GUID")
where the brand is the brand of the device IP, is IP address and
so here in this code how to add a horizontal scroll bar without overwriting the last line of the treeview table I tried to add the scrollbar but it's displaying on the last row of the table it should display below the last row of the table
Try this an example.
import tkinter as tk
from tkinter import ttk
class Chrisdb1(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tvw_results = ttk.Treeview(self, style = 'mystyle.Treeview')
self.insert = self.tvw_results.insert
self.tvw_results.grid(row = 0, column = 0, sticky='nsew')
self.tvw_results.column("#0", minwidth = 1150)
self.tvw_results.heading('#0', text = 'Found results', anchor = tk.W)
# Scrollbars + attach scrollbars to TreeView
sb_vertical = tk.Scrollbar(self, orient = "vertical", command = self.tvw_results.yview)
sb_horizontal = tk.Scrollbar(self, orient = "horizontal", command = self.tvw_results.xview)
self.tvw_results.configure(yscrollcommand = sb_vertical.set, xscrollcommand = sb_horizontal.set)
sb_vertical.grid(row = 0, column = 1, sticky = "ns")
sb_horizontal.grid(row = 1, column = 0, sticky = "ew")
# Configure and position grid for TreeView
self.grid_rowconfigure(0, weight = 1)
self.grid_columnconfigure(0, weight = 1)
def main():
'''test code for Chrisdb1 class'''
root = tk.Tk()
cnt_treeview = Chrisdb1(root)
for i in range(20):
cnt_treeview.insert('', tk.END, text = f'Row {i}: Some very long texxxxxxxt.....'*6)
cnt_treeview.pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == '__main__':
main()

Scrollbar of my app is working not correctly when content is large what must I do?

from tkinter import *
#Root
root = Tk()
root.title('A WINDOW')
#Frame
main_frame = Frame(root)
main_frame.pack(fill=BOTH, expand = True)
#Canvas
main_canvas = Canvas(main_frame)
main_canvas.pack(side = LEFT, fill = BOTH, expand = True)
#Scrollbar
scrollbar = Scrollbar(main_frame, orient = VERTICAL, command = main_canvas.yview)
scrollbar.pack(side = RIGHT, fill = 'y')
#Configure the Canvas
main_canvas.configure(yscrollcommand=scrollbar.set)
#Frame#2
Frame2 = Frame(main_canvas)
main_canvas.create_window((0, 0), window = Frame2, anchor = 'nw')
main_canvas.bind('<Configure>', lambda e :main_canvas.configure(scrollregion=main_canvas.bbox('all')))
for i in range(2000):
Button(Frame2, text = str(i)).grid(row = i, column = 0)
root.mainloop()
and when I execute the program, it works until the 1080th one then scrollbar moves but buttons don't go down anymore I hope you understood me and have an idea about what must I do...
This is a slight modification of your code. It demonstrates the limitation of the window object in tk.Canvas with a maximum height of 32768. It can be shown by changing variable offset to some arbitrary value and scrolling to the end of canvas. The last button will still be visible even though its position is 32768+offset.
Function bookmark finds frame2 in the window object and finds all objects in frame2 then changes background color. This makes it easy to confirm first and last buttons are visible.
import tkinter as tk
root = tk.Tk()
frame = tk.LabelFrame(root, labelanchor = tk.S, text = '0|0')
frame.grid(row = 0, column = 0, sticky = tk.NSEW)
for a in [root, frame]:
a.rowconfigure(0, weight = 1)
a.columnconfigure(0, weight = 1)
main_canvas = tk.Canvas(frame)
main_canvas.grid(row = 0, column = 0, sticky = tk.NSEW)
scrollbar = tk.Scrollbar(frame, orient = tk.VERTICAL, command = main_canvas.yview)
scrollbar.grid(row = 0, column = 1, sticky = tk.NS)
main_canvas.configure(yscrollcommand = scrollbar.set)
def location(event):
x, y = main_canvas.canvasx(event.x), main_canvas.canvasy(event.y)
frame['text'] = f'{x} | {y}'
# bind mouse
main_canvas.bind('<Motion>', location)
frame2 = tk.Frame(main_canvas)
# frame is positioned at offset
offset = 0
main_canvas.create_window(0, offset, window = frame2, anchor = tk.NW)
def bookends(x):
# Find reference to frame2
C = main_canvas.winfo_children()[0]
# find all objects in frame2
D = C.winfo_children()
print(len(D))
# change colors of first and last buttons
D[0]['background'] = 'red'
D[x]['background'] = 'red'
for i in range(2000):
tk.Button(
frame2,
text = str(i),
font = '{Courier New} 6',
padx=0, pady=0).grid(
row = i, column = 0, ipadx = 0, ipady = 0)
bookends(1999)
# main_canvas['scrollregion'] = f'0 0 40 {32768+offset}'
main_canvas.bind('<Configure>', lambda e :main_canvas.configure(scrollregion=main_canvas.bbox('all')))
root.mainloop()

How to remove unwanted scrollable space in Tkinter window

Assume a small Tkinter window with two frames, one having 20 buttons vertically and the other having 100 buttons vertically. These frames be one below the other. The window is small and so I create a scrollbar like this:
from tkinter import*
root = Tk()
root.geometry('200x100')
main_frame = Frame(root)
main_frame.pack(fill = BOTH, expand = 1)
main_canvas = Canvas(main_frame, bg = 'snow')
main_canvas.pack(side = LEFT, fill = BOTH, expand = 1)
vertical_scrollbar = ttk.Scrollbar(main_frame, orient = VERTICAL, command = main_canvas.yview)
vertical_scrollbar.pack(side = RIGHT, fill = Y)
main_canvas.configure(yscrollcommand = vertical_scrollbar.set)
main_canvas.bind('<Configure>', lambda e: main_canvas.configure(scrollregion = main_canvas.bbox("all")))
screen_frame = Frame(main_canvas, bg = 'snow')
main_canvas.create_window((0,0), window = screen_frame, anchor = 'nw')
frame1 = Frame(screen_frame, bg = 'snow').grid(row = 0, column = 0)
frame2 = Frame(screen_frame, bg = 'snow').grid(row = 1, column = 1)
for i in range(0, 20):
Button(frame1, text = 'Button').grid(row = i, column = 0)
for j in range(0, 100):
Button(frame2, text = 'Button').grid(row = j, column = 0)
root.mainloop()
So at this point, we will be able to scroll till the end of the second frame. But Now if I do the following:
for widgets in frame2.winfo_children():
widgets.destroy()
Frame 2 becomes empty. But now the scrollbar doesn't end at the end of frame1. Rather there is an empty space below frame1 where 100 buttons of frame2 used to be.
So my doubt is, how do we remove this empty space?

Is it possible to grab a label variable and put into list with tkinter

I've created a temperature converter programme in which the calculated temperature from an entry widget gets displayed in a separate label, what I need to do is to grab that converted variable and put it into a list.
I think that making a connected entry widget to the label widget would work where they are connected so I could grab the variable using the .get method but that would look awfully messy. Is there any other way I could proceed with this?
This is my first post and I am a beginner in Python, very sorry if the code looks messy and if I included too much code.
data = []
tempVal = "Celcius"
def store_temp(sel_temp):
global tempVal
tempVal = sel_temp
class Calculator:
def __init__(self, num_a, num_b):
self.num_a= num_a
self.num_b = num_b
def convert(self):
if tempVal == 'Fahrenheit':
return float((float(self.num_a) - 32)* 5 / 9)
if tempVal == 'Celcius':
return float((float(self.num_a) * 9/ 5) + 32)
def display_add(entry_numa,entry_numb,label_answer):
#get the value from entry_numa
num_a = entry_numa.get()
num_b = entry_numb.get()
num_a = str(num_a)
num_b = str(num_b)
#create an object
global data
calc = Calculator(num_a,num_b)
label_answer['text'] = calc.convert()
data += [calc]
def calc_history():
global data
#creat e another window
window_calc_list = Tk()
window_calc_list.geometry("400x200")
#create a listbox
listbox_calc_list = Listbox(window_calc_list, width= 300)
listbox_calc_list.pack()
listbox_calc_list.insert(END, "list of data")
for info in data:
listbox_calc_list.insert(END, str(info.num_a) + " " + str(info.num_b) + " " )
window_calc_list.mainloop()
def main():
window = Tk()
window.geometry("500x150")
validate_letter = window.register(only_letters)
validate_nb = window.register(only_numbers_max_3)
label = Label(window, width = 30, background = 'lightblue', text='enter temperature, only numbers')
label.grid(row=0, column=0)
entry_numa = Entry(window, width = 30, validate="key", validatecommand=(validate_nb, '%d', '%P'))
entry_numa.grid(row = 0, column = 1)
#create another label and entry object for num_b
label_numb = Label(window, width = 30, background = 'lightblue', text='enter location, only letters')
label_numb.grid(row=1, column=0)
entry_numb = Entry(window, width = 30, validate="key", validatecommand=(validate_letter, '%d', '%S'))
entry_numb.grid(row = 1, column = 1)
#create another label to display answer
label_answer = Label(window, width = 30, background = 'lightyellow')
label_answer.grid(row = 2, column = 1)
entry_answer = Entry(window, width = 30)
entry_answer.grid(row = 2, column = 0)
button_add = Button(window, text = "ADD", command = lambda: display_add(entry_numa,entry_numb,label_answer))
button_add.grid(row=3, column = 0)
button_delete = Button(window, text = "DELETE", command = lambda: delete_data(data))
button_delete.grid(row=3, column = 2)
#create another button to display all previous calculations
button_display = Button(window,text = "calc_history", command = lambda: calc_history())
button_display.grid(row=3, column = 1)
var = StringVar()
dropDownList = ["Celcius", "Fahrenheit"]
dropdown = OptionMenu(window, var,dropDownList[0], *dropDownList, command=store_temp)
dropdown.grid(row=0, column=2)
window.mainloop()
A tk.Label displayed value can be accessed via the text property
, labelwidgetname['text'].
Depeneding on when and how you want the independent list of stored values
to be updated there are a variety of options. The example shows one if the
user is required to press a submission button. This could be adapted,
for example,when the tempreture calculation is performed.
Of course it would be simpler to update the list of stored values directly at the point in the script where the calculated tempreture for the label text has been derived.
import tkinter as tk
stored_values = []
def add_labelvalue_tolist(temp):
'''Store label value to list.'''
stored_values.append(temp)
print('contents of list', stored_values)
def add_entry_tolabel(event):
display_label['text'] = user_entry.get()
ROOT = tk.Tk()
user_entry = tk.Entry()
user_entry.grid(column=0, row=0)
user_entry.bind('<KeyRelease>', add_entry_tolabel)
display_label = tk.Label()
display_label.grid(column=1, row=0)
# update list via button command linked to label text value
add_button = \
tk.Button(text='add to list',
command=lambda:add_labelvalue_tolist(display_label['text']))
add_button.grid(column=0, row=1)
ROOT.mainloop()
try making a function that is like this
def letterused():
converter=(letter.get())# letter is a entry box at the bottom is the code
converted.set(converter)
for i in range(1):
used_letters1.append(converter) #list
letter = ttk.Entry(root, width = 20,textvariable = letter)
letter.pack()

Returning a value from entry box to start sense hat timer

I am trying to start a count down timer to display on sense hat when I run the code it doesn't get the value typed into the entry box with no error returned just displays a 0 on the sense hat
from sense_hat import SenseHat
from tkinter import *
#set up
window = Tk()
window.title('timer')
window.geometry("300x100") #wxh
window.resizable(0,0)
#define and place labels
box1 = Label(window, text="time: ")
box1.grid(row = 1, column = 1,padx = 5, pady = 5)
#define entry box
answerVar = IntVar()
answertext = Entry(window,textvariable=answerVar)
string_answer = answertext.get()
int_answer = int(string_answer)
#display boxes
answertext.grid(row = 1, column = 2)
#define and place buttons
buttonstart = Button( window,text ='start:', command=lambda:int_answer)
sense = SenseHat()
G = [128,0,128] #led color
for i in range(int_answer,-1,-1): #create range start from input, stop at
#0 is -1
#decrease in steps is -1 Range is only a number
sense.show_letter(str(i),G)
exitbtn = Button( window,text ='Exit', command=exit)
#place buttons
buttonstart.grid(row = 4, column = 1,padx = 1, pady = 1)
exitbtn.grid(row = 4, column = 2,padx = 1, pady = 1)
#display window
window.mainloop()

Categories

Resources