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()
Related
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.
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
Right now, after I press the 'Time Range' button and call the calculateTime function, the text widget would appear with the results that I've inserted into it. However, after that, whenever I close the GUI window, the program would freeze and I'll have to forced quit it. This is my code:
import tkinter
from tkinter import *
import math
from tkinter import messagebox
class MyClass(tkinter.Frame):
def __init__(self, *args, **kwargs):
tkinter.Frame.__init__(self, *args, **kwargs)
#Setting up frame and widgets
vcmd1 = (self.register(self.__vcmd1), '%P', '%S')
vcmd2 = (self.register(self.__vcmd2), '%P')
vcmd3 = (self.register(self.__vcmd3), '%P', '%S')
label_iso = Label(self,text="Isotope A, Element")
label_vol = Label(self, text="Voltage")
label_range = Label(self, text="Charge Range")
label_iso.grid(row=0, column=0, sticky=E)
label_vol.grid(row=1, column=0, sticky=E)
label_range.grid(row=2, column=0, sticky=E)
self.entry1 = tkinter.Entry(self, validate="key", validatecommand=vcmd1)
self.entry2 = tkinter.Entry(self, validate="key", validatecommand=vcmd2)
self.entry3 = tkinter.Entry(self, validate="key", validatecommand=vcmd3)
self.entry1.grid(row=0, column=1)
self.entry2.grid(row=1, column=1)
self.entry3.grid(row=2, column=1)
def __vcmd1(self, P, S):
validString = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,1234567890'
if not S in validString:
return False
if "," in P:
if (len(P) - 1) > len(P.replace(",","")):
return False
messagebox.showinfo("Error", "Expected Form: ex. 133,Cs")
else:
return True
def __vcmd2(self, P):
if P == '':
return True
try:
float(P)
return True
except ValueError:
messagebox.showinfo("Error", "Entry is not a float or integer")
return False
def __vcmd3(self, P, S):
if "," in P:
if len(P.split(",")) > 2:
return False
a = P.split(",")[0]
b = P.split(",")[1]
if a != '' and b != '':
try:
int(a)
int(b)
except ValueError:
messagebox.showinfo("Error", "Expected form: ex. 1,12")
return False
else:
return True
class TimeGenerator:
def __init__(self,master):
frame = MyClass(master)
frame.grid(columnspan=2)
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
self.text = Text(root)
self.iso = frame.entry1
self.vol = frame.entry2
self.r = frame.entry3
def calculateTime(self):
x = 5
if self.r.get() == "" or self.iso.get() == "" or self.vol.get() == "":
messagebox.showinfo("Error", "No field can be empty")
return None
self.iso = self.iso.get().replace(" ", "")
list = []
for e in self.iso.split(","):
list.append(e)
f = open("/Users/LazyLinh/PycharmProjects/mass.mas12.txt", "r")
i = 0
while (i < 40):
header = f.readline()
i += 1
self.mass = 0
#iterate through text file
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1].lower() == columns[4].lower()):
if (len(columns) == 16):
self.mass = float(columns[13].replace("#","")) + float(columns[14].replace("#",""))
else:
self.mass = float(columns[12].replace("#","")) + float(columns[13].replace("#",""))
#Calculation
self.r = self.r.get().replace(" ", "")
tup = tuple(int(x) for x in self.r.split(","))
list = []
for q in range(tup[0], tup[1] + 1):
y = (x * math.sqrt(self.mass * 1.6605402e-27 / (2 * q * float(self.vol.get())))) * 10e6
list.append(y)
i = tup[0]
#inserting to text widget
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
self.text.pack()
root = Tk()
b = TimeGenerator(root)
root.mainloop()
I've tried to searched up on this topic, but I'm not really using any weird update() function, and text shows up after the function is finished, so how likely that it is an event loop problem? Am I also doing something wrong that could cause this problem?
Thank you!
You have widgets in the root window that use both pack and grid. You cannot do this. Within a given container (root window, frame, etc) you can use one or the other, but not both.
The reason your program freezes is due to pack and grid fighting to gain control of the layout. When you pack the text widget it causes a change in the size and/or position of other widgets in the root window. That triggers grid to try to re-layout the widgets it is responsible for. This triggers pack to try to re-layout the widgets it is responsible for, and on and on until the end of time.
My guess is that you need to use grid with self.text since you use grid everywhere else.
Problem: you can scroll upwards even though the first item should be at the very top of the canvas
How to reproduce the problem: have at least one item on the canvas and scroll using the mouse ( press space to make an item )
Note: the problem ceases once the items are wider than the canvas itself
Sample code
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.bind("<MouseWheel>", self.scroll)
self.bind("<KeyPress>", self.keypressed)
self.TargetCanvas = None
self.makeui()
def makeui(self):
self.Canvas = tk.Canvas(self, bg = "white")
self.Canvas.grid(row = 0, column = 0, sticky = "W")
sby = tk.Scrollbar(self, orient = "vertical", command = self.Canvas.yview)
sby.grid(row = 0, column = 1, sticky = "ns")
self.Canvas.configure(yscrollcommand = sby.set)
self.CanvFrame = tk.Frame(self.Canvas, bg = "white")
self.Canvas.create_window((0, 0), window = self.CanvFrame, anchor = "nw")
self.CanvFrame.bind("<Configure>", lambda event: self.Canvas.configure(scrollregion = self.Canvas.bbox("all")))
self.Canvas.bind("<Enter>", lambda event: self.settarget(event, True))
self.Canvas.bind("<Leave>", lambda event: self.settarget(event, False))
tk.Label(self, text = "space = add item, c = clear all").grid(row = 1, column = 0)
def settarget(self, event, check):
if check:
self.TargetCanvas = event.widget
else:
self.TargetCanvas = None
def scroll(self, event):
if self.TargetCanvas is not None:
direction = 0
if event.num == 5 or event.delta == -120:
direction = 1
if event.num == 4 or event.delta == 120:
direction = -1
self.TargetCanvas.yview_scroll(direction, tk.UNITS)
def keypressed(self, event):
if event.keysym == "space":
self.additem()
elif event.keysym == "c":
self.clearall()
def clearall(self):
for i in self.CanvFrame.winfo_children():
i.destroy()
x = tk.Label(self.CanvFrame)
#kick in frame resizing
x.pack()
self.update()
self.Canvas.configure(scrollregion = self.Canvas.bbox("all"))
x.destroy()
def additem(self):
tk.Label(self.CanvFrame, text = "asd").pack(side = tk.TOP)
def main():
App().mainloop()
if __name__ == "__main__":
main()
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()