Toggling variables from for loop in python and tkinter - python-3.x

I'm new with python and stack overflow so sorry if this question is below average. Anyway, I'm trying to make a Registration Software with python and tkinter, and I want to make it so that the buttons toggle between the purple colour: #ff4dd2. It is made hard because the buttons are created from a loop, I can't assign a variable to the buttons. If you could take the time to take a look at this it would be really appreciated :) (The current code works as expected, hopefully you can understand what I mean)
from tkinter import *
import time
import datetime
import re
root = Tk()
root.title("Attendence Register")
root.geometry('1350x650+0+0')
root.resizable(False, False)
nameframe = Frame(root, height=650, width=300)
nameframe.pack(side='left')
saveframe = Frame(root, height=650, width=300)
saveframe.pack(side='right')
outlist = []
def saveDataPresent(line):
present[line].configure(bg='#ff4dd2')
line = (line + ' is present')
outlist.append(line)
#print(outlist)
def saveDataAbsent(line):
absent[line].configure(bg='#ff4dd2')
line = (line + ' is absent')
outlist.append(line)
#print(outlist)
def saveDataIll(line):
ill[line].configure(bg='#ff4dd2')
line = (line + ' is ill')
outlist.append(line)
#print(outlist)
def saveDataHoliday(line):
holiday[line].configure(bg='#ff4dd2')
line = (line + ' is on holiday')
outlist.append(line)
#print(outlist)
def saveData():
now = datetime.datetime.now()
now = str(now)
dire = 'logs/'
now = dire + now
now = re.sub(':', '', now)
now += '.txt'
log = open(now, "w+")
log.close()
log = open(now, "a")
for i in outlist:
i = (i + '\n')
log.write(i)
log.close()
text = open('names.txt','r')
line = text.readline()
count = 0
present = {}
absent = {}
ill = {}
holiday = {}
for line in text:
count+= 1
name = Label(nameframe, text=line)
name.grid(row=count, column = 0)
present[line] = Button(nameframe, text='/', pady = 20, padx=20, bg ='#66ff66', command=lambda line=line: saveDataPresent(line))
present[line].grid(row=count, column = 2)
holiday[line] = Button(nameframe, text='H', pady=20, padx=20, bg='light blue', command=lambda line=line: saveDataHoliday(line))
holiday[line].grid(row=count, column=3)
ill[line] = Button(nameframe, text='ill', pady=20, padx=20, bg ='#ffa31a', command=lambda line=line: saveDataIll(line))
ill[line].grid(row=count, column=4)
absent[line] = Button(nameframe, text='NA', pady=20, padx=20, bg ='#ff6666', command=lambda line=line: saveDataAbsent(line))
absent[line].grid(row=count, column=5)
savebut = Button(saveframe, text='Save', pady = 20, padx=20, command=saveData)
savebut.pack()
root.mainloop()

I put this in the comments but it didnt look nice:
def saveDataHoliday(line):
holidaycount[line] += 1
if holidaycount[line] % 2 == 1:
holiday[line].configure(bg='#ff4dd2')
line = (line + ' is holiday')
outlist.append(line)
#print(outlist)
else:
holiday[line].configure(bg='light blue')
line = (line + ' is holiday')
outlist.remove(line)
#print(outlist)enter code here
holidaycount was defined earlier as a dictionary:
holidaycount = {}
I did this for each button(absent, present etc) Then after that:
for line in text:
count+= 1
name = Label(nameframe, text=line)
name.grid(row=count, column = 0)
presentcount[line] = 0
absentcount[line] = 0
illcount[line] = 0
holidaycount[line] = 0

Related

Problem with askopenfilename() sending to converting function and saving file using asksavefile() - Python Tkinter

I wrote a CAD coordinate conversion application that reads a .txt file using filedialok.askopenfilename() using the function read_file_click().
After selecting the appropriate scale in the Combobox, the program converts the file using the convert() function, then saves it to a .txt file after calling the function save_file_click().
The problem is that when I send the returned value from the convert function to the save_file_click() function, I get two notifications about opening the file.
I don't know how to correct this error. I tried using global variables, but it doesn't help, and weak errors appears with the data_list_no_head variable. Thanks for help:)
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
import os
root = Tk()
root.title("Autocad Coordinate Converter")
root.geometry("")
root.geometry("280x320")
root.resizable(False, False)
def combo_sets():
scale_combo.set("")
def ending_message():
messagebox.showinfo("Autocad Coordinate Converter", "End")
def read_file_click():
global data_list_no_head
file_path = filedialog.askopenfilename()
return file_path
def convert():
file_path_new = read_file_click()
data_list = []
with open(file_path_new, encoding='utf-16') as file:
for line in file:
data_list.append(line.split())
data_list_no_head = data_list[4:]
return data_list_no_head
def save_file_click():
new = convert()
scale_get = scale_combo.get()
data = None
event_eng = None
cal = None
x_coordinate = None
y_coordinate = None
output_file = open(output_file_path_name, 'a')
if scale_get == "1:500" or scale_get == "1:1000":
for event in new:
for _ in event:
data = event[1]
event_eng = event[4]
x_coordinate = event[5]
y_coordinate = event[6]
cal = int(event_eng[-1])*2-2
output_file.write(f"_layer u w{data[2:4]}e{event_eng[-1]} _donut 0 {cal} {y_coordinate},"
f"{x_coordinate} \n")
output_file.close()
new_file_name = output_file_path_name[:-4] + ".scr.txt"
os.rename(output_file_path_name, new_file_name)
combo_sets()
ending_message()
elif scale_get == "1:2000":
for event in new:
for _ in event:
data = event[1]
event_eng = event[4]
x_coordinate = event[5]
y_coordinate = event[6]
cal = 2*(int(event_eng[-1])*2-2)
output_file.write(f"_layer u w{data[2:4]}e{event_eng[-1]} _donut 0 {cal} {y_coordinate},"
f"{x_coordinate} \n")
output_file.close()
new_file_name = output_file_path_name[:-4] + ".scr.txt"
os.rename(output_file_path_name, new_file_name)
combo_sets()
ending_message()
elif scale_get == "1:5000":
for event in new:
for _ in event:
data = event[1]
event_eng = event[4]
x_coordinate = event[5]
y_coordinate = event[6]
cal = 5*(int(event_eng[-1])*2-2)
output_file.write(f"_layer u w{data[2:4]}e{event_eng[-1]} _donut 0 {cal} {y_coordinate},"
f"{x_coordinate} \n")
output_file.close()
new_file_name = output_file_path_name[:-4] + ".scr.txt"
os.rename(output_file_path_name, new_file_name)
combo_sets()
ending_message()
elif scale_get == "1:10000":
for event in new:
for _ in event:
data = event[1]
event_eng = event[4]
x_coordinate = event[5]
y_coordinate = event[6]
cal = 20*(int(event_eng[-1])-2)
output_file.write(f"_layer u w{data[2:4]}e{event_eng[-1]} _donut 0 {cal} {y_coordinate},"
f"{x_coordinate} \n")
output_file.close()
new_file_name = output_file_path_name[:-4] + ".scr.txt"
os.rename(output_file_path_name, new_file_name)
combo_sets()
ending_message()
# Frame1
frame1 = LabelFrame(root, padx=15, pady=15, relief=FLAT)
frame1.grid(row=1, column=0)
button_1 = Button(frame1, text="Read .txt file", padx=15, pady=15, width=20, height=1, command=read_file_click)
button_1.grid(row=1, column=0, padx=3, pady=3)
# Frame2
frame2 = LabelFrame(root, padx=15, pady=15, relief=FLAT)
frame2.grid(row=2, column=0)
Label(frame2, text="Select scale:", width=14).grid(row=1, column=1, padx=1, pady=1)
scale_combo = ttk.Combobox(frame2, values=["1:500", "1:1000", "1:2000", "1:5000", "1:10000"], width=9, state='readonly')
scale_combo.current()
scale_combo.grid(row=2, column=1, padx=1, pady=1)
# Frame3
frame3 = LabelFrame(root, padx=50, pady=50, relief=FLAT)
frame3.grid(row=3, column=0)
button_2 = Button(frame3, text="Save file in CAD format", padx=15, pady=15, width=20, height=1,
command=save_file_click)
button_2.grid(row=0, column=0, padx=3, pady=3)
root.mainloop()

Get OptionMenu value after selection and store in array

Here is the code:
from tkinter import *
class Window(Canvas):
def __init__(self,master=None,**kwargs):
Canvas.__init__(self,master,**kwargs)
self.frame = Frame(self)
self.create_window(0,0,anchor=N+W,window=self.frame)
self.row = 1
self.input_n_or_s = []
self._init_entries()
def _init_entries(self):
n_or_s = Label(self.frame, text='N or S', font='Helvetica 10 bold').grid(row = self.row, column = 1)
self.row += 1
def add_entry(self):
n_or_s = ['N', 'S']
variable = StringVar(self.frame)
variable.set(n_or_s[0])
option_n_or_s = OptionMenu(self.frame, variable, *n_or_s)
option_n_or_s.grid(row = self.row, column = 1)
self.row += 1
#def save_entry(self):
if __name__ == "__main__":
root = Tk()
root.resizable(0,0)
root.title('Lot')
lot = Window(root)
lot.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
lot.config(yscrollcommand = scroll.set)
scroll.config(command=lot.yview)
lot.configure(scrollregion = lot.bbox("all"), width=1000, height=500)
def add_points():
lot.add_entry()
lot.configure(scrollregion = lot.bbox("all"))
b1 = Button(root, text = "Add points", command = add_points)
b1.grid(row=1,column=0)
def get_value():
b1.destroy()
lot.save_entry()
b2 = Button(root, text = "Get value!", command = get_value)
b2.grid(row=2,column=0)
root.mainloop()
Can someone help me on what to put inside the 'save_entry()' function to get each values of the OptionMenus (assuming that the 'add entry' button has been clicked more than 5 times), and then put each values in the 'input_n_or_s' array for later use?
For example:
Here's the GUI wherein the user clicked the 'Add points' button 10 times, and then changed some default values to 'S':
My expected output should look like this:
['S', 'N', 'N', 'S', 'N', 'N', 'N', 'S', 'N', 'S']
Here you go I think this is what you want.
from tkinter import *
class Window(Canvas):
def __init__(self,master=None,**kwargs):
Canvas.__init__(self,master,**kwargs)
self.frame = Frame(self)
self.create_window(0,0,anchor=N+W,window=self.frame)
self.row = 1
self.input_n_or_s = []
self._init_entries()
def _init_entries(self):
n_or_s = Label(self.frame, text='N or S', font='Helvetica 10 bold').grid(row = self.row, column = 1)
self.row += 1
def add_entry(self):
n_or_s = ['N', 'S']
self.variable = StringVar(self.frame)
self.variable.set(n_or_s[0])
self.menu = option_n_or_s = OptionMenu(self.frame, self.variable, *n_or_s)
option_n_or_s.grid(row = self.row, column=1)
self.row += 1
def save_entry(self):
print(self.variable.get())
if __name__ == "__main__":
root = Tk()
root.resizable(0, 0)
root.title('Lot')
lot = Window(root)
lot.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
lot.config(yscrollcommand = scroll.set)
scroll.config(command=lot.yview)
lot.configure(scrollregion = lot.bbox("all"), width=1000, height=500)
root.cnt = 0
def add_points():
root.cnt += 1
if root.cnt < 5:
return
root.cnt = 0
lot.add_entry()
lot.configure(scrollregion = lot.bbox("all"))
lot.input_n_or_s.append(lot.variable.get())
b1 = Button(root, text = "Add points", command = add_points)
b1.grid(row=1,column=0)
def get_value():
b1.destroy()
lot.save_entry()
b2 = Button(root, text = "Get value!", command = get_value)
b2.grid(row=2, column=0)
root.mainloop()
I finally figured it out. The reason that I can't manage to make it work before is that I'm trying to get the output from the OptionMenu instead of the variable.
def add_entry(self):
....
self.input_n_or_s.append(variable)
def save_entry(self):
for entry in self.input_n_or_s:
x = str(entry.get())
self.north_or_south.append(x)
print(self.north_or_south)
So here's the whole working code:
from tkinter import *
class Window(Canvas):
def __init__(self,master=None,**kwargs):
Canvas.__init__(self,master,**kwargs)
self.frame = Frame(self)
self.create_window(0,0,anchor=N+W,window=self.frame)
self.row = 1
self.input_n_or_s = []
self.north_or_south = []
self._init_entries()
def _init_entries(self):
n_or_s = Label(self.frame, text='N or S', font='Helvetica 10 bold').grid(row = self.row, column = 1)
self.row += 1
def add_entry(self):
n_or_s = ['N', 'S']
variable = StringVar(self.frame)
variable.set(n_or_s[0])
option_n_or_s = OptionMenu(self.frame, variable, *n_or_s)
option_n_or_s.grid(row = self.row, column = 1)
self.row += 1
self.input_n_or_s.append(variable)
def save_entry(self):
for entry in self.input_n_or_s:
x = str(entry.get())
self.north_or_south.append(x)
print(self.north_or_south)
if __name__ == "__main__":
root = Tk()
root.resizable(0,0)
root.title('Lot')
lot = Window(root)
lot.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
lot.config(yscrollcommand = scroll.set)
scroll.config(command=lot.yview)
lot.configure(scrollregion = lot.bbox("all"), width=1000, height=500)
def add_points():
lot.add_entry()
lot.configure(scrollregion = lot.bbox("all"))
b1 = Button(root, text = "Add points", command = add_points)
b1.grid(row=1,column=0)
def get_value():
b1.destroy()
lot.save_entry()
b2 = Button(root, text = "Get value!", command = get_value)
b2.grid(row=2,column=0)
root.mainloop()
Still, thanks for the effort on helping me, Daniel Huckson. And Bryan Oakley, thanks for your concern also.

Tkinter: How do I clear the window?

So this program asks for a name and last name. I'm looking for the program to clear and show "Welcome " + name + " " + lastname.
import sys
from tkinter import *
def salir():
sys.exit()
root = Tk()
root.wm_title('Matricula UTEC')
Label(root, text = "Bienvenido a Matricula UTEC").grid(row = 0)
Label(root, text = "Ingrese sus nombres: ").grid(row = 1)
Label(root, text = "Ingrese sus apellidos: ").grid(row = 2)
e1 = Entry(root)
e2 = Entry(root)
e1.grid(row=1, column = 1)
e2.grid(row=2, column = 1)
Button(root, text = 'Salir', command = salir).grid(row = 4, column = 0, sticky = W, pady = 4)
Button(root, text = 'Comenzar', command = salir).grid(row = 4, column = 1, sticky = W, pady = 4)
root.mainloop()
The simplest solution is to put everything you want to "clear" in a frame. Then, you can simply delete the frame and replace it with a different frame.
Here's a really simple example:
import sys
from tkinter import *
def salir():
login_frame.destroy()
home_frame = home()
home_frame.pack(fill="both", expand=True)
def login():
frame = Frame(root)
Label(frame, text = "Bienvenido a Matricula UTEC").grid(row = 0)
Label(frame, text = "Ingrese sus nombres: ").grid(row = 1)
Label(frame, text = "Ingrese sus apellidos: ").grid(row = 2)
e1 = Entry(frame)
e2 = Entry(frame)
e1.grid(row=1, column = 1)
e2.grid(row=2, column = 1)
Button(frame, text = 'Salir', command = salir).grid(row = 4, column = 0, sticky = W, pady = 4)
Button(frame, text = 'Comenzar', command = salir).grid(row = 4, column = 1, sticky = W, pady = 4)
return frame
def home():
frame = Frame(root)
Label(frame, text="Welcome").pack()
return frame
root = Tk()
root.wm_title('Matricula UTEC')
login_frame = login()
login_frame.pack(fill="both", expand=True)
root.mainloop()

Frame/grid don't clear themselves when updated

I tried to build a calendar which shows current month of the year, and by pressing << and >> buttons, one can see the previous or next month.
Code seems to work at first sight, but when you want to see the previous/next months, the frame doesn't clear itself completely, and shows the residual days form the previous months, like 31 for months which only has 30 days.
I couldn't figure out how to remove them. Can you guys please help me? thanks
from tkinter import Tk, RAISED, Label, Button, Frame
class org(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
def organizer(self, xx, yy):
from calendar import monthrange, month
monthname = str()
m = month(yy, xx)
for i in m:
if i == '\n':
break
monthname +=i
previous = Button(self, text = '<<', command = self.prev)
previous.grid(row = 0, column = 0)
nextt = Button(self, text = '>>', command = self.ntt)
nextt.grid(row = 0, column = 6)
month = Label(self, text = monthname+ ' ')
month.grid(row = 0, column = 1, columnspan = 5)
labels = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
for i in range(len(labels)):
days = Label(self, text = labels[i], width = 3)
days.grid(row = 1, column = i)
(startday, endday) = monthrange(yy, xx)
r = 2
for i in range(0,startday):
label = Label(self, width=3, text=' ')
label.grid(row = 2, column = i)
for i in range(1, endday+1):
label = Button(self, text = i, width = 3)
label.grid(row = r, column = startday)
startday +=1
if startday > 6:
startday -= 7
r += 1
for i in range(startday, 7):
label = Label(self, width=3, text=' ')
label.grid(row = r, column = i)
class Cal(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.x = 10 #Oct
self.y =2016 #2016
org.organizer(self,self.x, self.y)
def prev(self):
Frame.grid_remove(self)
self.x -= 1
if self.x==0:
self.x = 1
else:
org.organizer(self,self.x, self.y)
def ntt(self):
self.x += 1
if self.x==13:
self.x = 12
else:
org.organizer(self,self.x, self.y)
root = Tk()
a = Cal(root)
a.pack()
root.mainloop()
Seems like you want to remove all the widgets drawn on Tk() and redraw it. You can delete all widgets with the following code:
for child in root.winfo_children():
child.destroy()

Display of a large amount of data in a Canvas with a Scrollbar

I'm having a problem trying to display a large table in tkinter.
First, I tried to display all label at once in the canvas, but over few hundred rows, the program shut down. So I tried to create a scrollable canvas that updates everytime I scroll: I collect the position of the scrollbar and depending on the position of it, I display the 10 values corresponding.
But I can't get this code working. For now it only displays a black background with the scrollbar on the right.
Here is the code:
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = []
for i in range(1, 1000):
self.x.append(i)
self.parent = parent
self.mainFrame = Frame(self.parent)
self.mainFrame.pack()
self.canvas = Canvas(self.mainFrame, width = 200, height = 500, bg = "black")
self.canvas.grid(row = 0, column = 0)
self.scroll = Scrollbar(self.mainFrame, orient = VERTICAL, command = self.update)
self.scroll.grid(row = 0, column = 1)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.tabCursor = 0
self.scrollPosition = self.scroll.get()
def update(self):
self.tabCursor = round(self.scrollPosition[0]*len(self.x))
if ((len(self.x) - self.tabCursor) < 10):
self.tabCursor = len(self.x) - 10
for i in range(0, 10): #display 10 values
label = Label(self.canvas, text = str(self.x[tabCursor + i]), width = 50)
label.grid(column = 0, row = i)
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
EDIT :
I finally had time to implement your answer. It looks fine but I can't get the scrollbar working and i don't know why.
class TableauDeDonnees(object):
"Tableau de données -- Onglet Tableau de données"
def __init__(self, data, parent):
self.parent = parent
self.data = data
print(self.data[0], self.data[1])
print(len(self.data[0]), len(self.data[1]))
self.labels = []
self.navigationFrame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg = "black", width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigationFrame.pack()
print(len(data))
for row in range(50):
for column in range(len(data)):
self.labels.append(Label(self.canvas, text = str(data[column][row])))
for i in range(len(self.labels)):
self.labels[i].grid(row = i // 2, column = i % 2, sticky = NSEW)
self.boutonRetour = Button(self.navigationFrame, text = "Retour", command = lambda: self.move(-2))
self.quickNav = Entry(self.navigationFrame, width = 3)
self.quickNav.bind('<Return>', lambda x: self.move(self.quickNav.get()))
self.boutonSuivant = Button(self.navigationFrame, text = "Suivant", command = lambda: self.move(0))
temp = divmod(len(data[0]), len(self.labels) // 2)
self.pages = temp[0] + (1 if temp[1] else 0)
self.position = Label(self.navigationFrame, text='Page 1 sur ' + str(self.pages))
self.pageCourante = 1
self.boutonRetour.grid(row = 0, column = 0)
self.quickNav.grid(row = 0, column = 1)
self.boutonSuivant.grid(row = 0, column = 2)
self.position.grid(row = 0, column = 3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command = self.canvas.yview)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.scroll.pack(side = RIGHT, fill='y')
self.canvas.pack(side = LEFT, fill = 'both')
self.canvas.create_window((4,4), window = self.mainFrame, anchor = "nw", tags = "frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def update(self, event):
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def move(self, direction):
if (self.pageCourante == 1 and direction == -2) or (self.pageCourante == self.pages and direction == 0):
return
if direction in (-2, 0):
self.pageCourante += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages + 1):
return
except ValueError:
return
else:
self.pageCourante = temp
for i in range(len(self.labels)):
try:
location = str(self.data[i % 2][len(self.labels)*(self.pageCourante - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text = location)
self.position.config(text = 'Page ' + str(self.pageCourante) + ' sur ' + str(self.pages))
I don't understand why the scrollbar isn't working properly. Note, that my parent is a notebook.
Also, there is a problem with the number of items displayed. The number of pages is right but it seems it displays more than it should cause last pages are empty and the last values displayed seems right.
Thank you for your attention
The scrollbar doesn't work by continuously creating new widgets ad infinitum. You were also missing some key parts - unfortunately, Scrollbar isn't as straightforward as most tkinter widgets.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.parent = parent
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.x = []
for i in range(1000):
self.x.append(Label(self.mainFrame, text=str(i)))
self.x[i].grid()
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
If you'd like to show only a few at a time and provide a forum-like interface, you can use Buttons to navigate between pages. This example allows the user to navigate with Back and Forward buttons, as well as by entering a page number in the box and pressing Enter.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = list(range(1000))
self.labels = []
self.parent = parent
self.navigation_frame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigation_frame.pack()
for i in range(100):
self.labels.append(Label(self.mainFrame, text=str(i)))
self.labels[i].grid()
self.back_button = Button(self.navigation_frame, text='Back', command=lambda: self.move(-2))
self.quick_nav = Entry(self.navigation_frame, width=3)
self.quick_nav.bind('<Return>', lambda x: self.move(self.quick_nav.get()))
self.forward_button = Button(self.navigation_frame, text='Forward', command=lambda: self.move(0))
temp = divmod(len(self.x), len(self.labels))
self.pages = temp[0] + (1 if temp[1] else 0)
self.you_are_here = Label(self.navigation_frame, text='Page 1 of ' + str(self.pages))
self.current_page = 1
self.back_button.grid(row=0, column=0)
self.quick_nav.grid(row=0, column=1)
self.forward_button.grid(row=0, column=2)
self.you_are_here.grid(row=0, column=3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def move(self, direction):
if (self.current_page == 1 and direction == -2) or (self.current_page == self.pages and direction == 0):
return
if direction in (-2, 0):
self.current_page += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages+1):
return
except ValueError:
return
else:
self.current_page = temp
for i in range(len(self.labels)):
try:
location = str(self.x[len(self.labels)*(self.current_page - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text=location)
self.you_are_here.config(text='Page ' + str(self.current_page) + ' of ' + str(self.pages))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()

Resources