Multiple parallel actions in tkinter's button command - python-3.x

I would like to add parallel actions in one button in tkinter window, this is my main code
from Fonctions import *
from time import time, sleep
listConnextion = [a,b,c,d,e,f]
MotDePasse= ""
class ConnecOptimizerApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
tk.Tk.iconbitmap(self , default= "logo.ico")
tk.Tk.wm_title(self,"ConnecOptimizer")
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
self.frames ={}
for f in (PageAccueil, PageAttente):
frame = f(container,self)
self.frames[f] = frame
frame.grid(row = 1000, column = 500, sticky = "nsew")
self.show_frame(PageAccueil)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class PageAccueil(tk.Frame):
def __init__(self,parent,controller):
def cocher():
if var4 == 0:
ip.configure(state='disabled')
else:
ip.configure(state='normal')
tk.Frame.__init__(self,parent)
Frame0 = ttk.Frame(self)
Frame0.pack(side="top")
Frame1 = ttk.Frame(Frame0)
Frame1.pack(side="left", padx=70, pady=50)
Frame2 = ttk.Frame(Frame0)
Frame2.pack(side="left", padx=10, pady=10)
Frame3 = ttk.Frame(self)
Frame3.pack(side="top")
Frame4 = ttk.Frame(Frame3)
Frame4.pack(side = "left")
Frame5 = ttk.Frame(Frame3)
Frame5.pack(side = "left")
Fr = ttk.Frame(self).pack(side = "top")
Frame6 = ttk.Frame(self)
Frame6.pack(side = "top")
Frame7 = ttk.Frame(Frame6)
Frame7.pack(side="left")
Frame8 = ttk.Frame(Frame6)
Frame8.pack(side="left")
Frame9 = ttk.Frame(self)
Fr2 = ttk.Frame(self).pack(side = "top")
Frame9.pack(side = "top")
Frame10 = ttk.Frame(Frame9)
Frame10.pack(side = "left")
Frame11 = ttk.Frame(Frame9)
Frame11.pack(side = "left")
Frame12 = ttk.Frame(self)
Frame12.pack(side = "top")
varGr = tk.StringVar()
varGr.set(0)
for i in range(len(listConnextion)):
b = ttk.Radiobutton(Frame1, variable=varGr, text=listConnextion[i], value=i)
b.grid(row=i , sticky = "w")
var1 = tk.IntVar()
ttk.Checkbutton(Frame2, text="Graphique", variable=var1).grid(row=1 ,sticky = "w" )
var2 = tk.IntVar()
ttk.Checkbutton(Frame2, text="Diagnostic", variable=var2).grid(row=2 , sticky = "w")
var3 = tk.IntVar()
ttk.Checkbutton(Frame2, text="Optimisation", variable=var3).grid(row=3 , sticky = "w")
lab = ttk.Label(Frame4, text = "Periode de reference de l'historique en jour ")
lab.pack(side = "left" , padx = 30 )
nbJour = ttk.Entry(Frame5)
nbJour.pack(side = "left" )
l = ttk.Label(Fr).pack()
lab2 = ttk.Label(Frame7, text = "Nombre d'entrées pour finir l'apprentissage")
lab2.pack(side = "left" , padx = 30)
nbEntre = ttk.Entry(Frame8)
nbEntre.pack(side = "left" )
l2 = ttk.Label(Fr2).pack()
var4 = tk.IntVar()
ttk.Checkbutton(Frame10 , text = "Iperf", variable = var4 , command = cocher).pack( padx = 10)
ip = ttk.Entry(Frame11 , state = 'disabled')
ip.pack(padx = 20)
B = ttk.Button(Frame12, text="Valider" , command = (lambda: controller.show_frame(PageAttente)))
B.pack(side = "top" , pady = 30)
class PageAttente(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
frame0 = ttk.Frame(self)
frame0.pack(side = "top")
frame1 = ttk.Frame(self)
frame1.pack(side = "top")
self.T = tk.Text(frame0, height=20, width=53)
self.S = ttk.Scrollbar(frame0)
self.T.config(yscrollcommand=self.S.set)
self.T.pack(side=tk.LEFT, fill=tk.Y)
self.S.config(command=self.T.yview)
self.S.pack(side=tk.RIGHT, fill=tk.Y)
self.updateWidgets()
ttk.Button(frame1, text = "Arreter Diagnostic", command = (lambda : controller.show_frame(PageAccueil)) ).pack(pady = 10)
def updateWidgets(self):
with open('text.txt') as f:
newText = f.read()
self.T.delete('1.0', tk.END)
self.T.insert(tk.END, newText)
self.after(1000, self.updateWidgets)
app = ConnecOptimizerApp()
app.geometry("450x400+300+140")
app.mainloop()
and here you can find my fonctions
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
def PageLogin():
root = tk.Tk()
root.geometry("350x130+530+280")
root.title("Super-utilisateur")
def leave():
MotDePasse = champMp.get()
print(MotDePasse)
root.destroy()
topFrame = ttk.Frame(root)
topFrame.pack()
middleFrame = ttk.Frame(root)
middleFrame.pack()
bottomFrame = ttk.Frame(root)
bottomFrame.pack()
lab1 = ttk.Label(topFrame, text=" ").pack()
lab2 = ttk.Label(topFrame, text="Veuillez entrer le mot de passe super-utilisateur").pack()
labelMessage2 = ttk.Label(middleFrame, text="mot de passe ")
labelMessage2.pack(side="left", padx=10, pady=10)
champMp = ttk.Entry(middleFrame, show='*')
champMp.pack(side="right", padx=10, pady=10)
b = ttk.Button(bottomFrame, text="valider", command = leave)
b.grid(row=4, pady=5, sticky="w")
root.mainloop()
def TracerGraphe ():
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax2 = fig.add_subplot(1, 1, 1)
ax3 = fig.add_subplot(1, 1, 1)
def animate(i):
graph_data = open('test.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
zs = []
ws = []
for line in lines:
if len(line) > 1:
x, y, z, w = line.split(',')
xs.append(x)
ys.append(y)
zs.append(z)
ws.append(w)
ax1.clear()
ax2.clear()
ax3.clear()
ax1.plot(xs, ys, label='RTT')
ax2.plot(xs, zs, label='Debit')
ax3.plot(xs, ws, label='taux d erreur')
ax1.legend()
ax2.legend()
ax3.legend()
ani = animation.FuncAnimation(fig, animate, interval=1000)
mngr = plt.get_current_fig_manager()
mngr.window.setGeometry(700, 100, 640, 545)
plt.show()
What I cant is : When I press the B button I want to show the PageAttente using "lambda: controller.show_frame(PageAttente)" , show the LoginPage using "PageLogin()" fonction and show the graph using "TracerGraphe ()"
I have tried all the solutions I found on net but it doesnt work
Can anyone help me please ?
Thanks

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

Tkinter - Canvas in new window and the image resize to the new window resolution

I'm trying to do a Canvas that display a picture in a new window with a pressing a button, actually that is working, but I need the display that show the image in the new windows resize to the new window dimension.
I already tried to manage to get the size to an specific but nothing really worked out for me.
Here is the code:
from tkinter import *
import requests
import shutil
from xml.dom.minidom import parse
import fileinput
import os.path as path
import os
import tempfile
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
root = Tk()
root.title("Etiquetas")
root.configure(width=1280,height=720)
root.geometry('{}x{}'.format(427, 600))
root.resizable(width=False, height=False)
canvas = Canvas(root, width=500, height=500)
canvas.pack(fill="both", expand=True)
my_image = PhotoImage(file='label.png')
def new_winF(): # new window definition
newwin = Toplevel(root)
display = Label(newwin, text="Humm, see a new window !")
display.pack()
def retrieve_input():
f = open('DataXML.xml', 'w+')
f.truncate(0)
inputParamString = ParamString.get("1.0","end-1c")
inputAlto = Alto.get("1.0","end-1c")
inputAncho = Ancho.get("1.0","end-1c")
inputTemplateLabel = TemplateLabel.get("1.0","end-1c")
#StringEtiqueta = open("DataXML.xml", "a+")
f.write(inputParamString)
f.close()
doc = parse("DataXML.xml")
my_node_list = doc.getElementsByTagName("label_param")
LabelResultado = open("Template.txt", "w")
LabelResultado.write(inputTemplateLabel)
LabelResultado.close()
for node in my_node_list:
name_node = node.getElementsByTagName("name")
value_node = node.getElementsByTagName("value")
y = ("[" + name_node[0].firstChild.data + "]")
z = y.upper()
print(z)
if (value_node[0].firstChild != None):
print(value_node[0].firstChild.data)
x = value_node[0].firstChild.data
else:
print("")
x = ""
with fileinput.FileInput("Template.txt", inplace=True) as file:
for line in file:
print(line.replace(z, x), end='')
w = open('Template.txt.bak', 'w+')
w.close()
codigoZPL = open("Template.txt", "r")
zpl = codigoZPL.read()
codigoZPL.close()
url = ('http://api.labelary.com/v1/printers/8dpmm/labels/'+inputAlto+'x'+inputAncho+'/0/')
files = {'file': zpl}
#headers = {'Accept': 'application/pdf'}
response = requests.post(url, headers=0, files=files, stream=True)
if response.status_code == 200:
response.raw.decode_content = True
with open('label.png', 'wb') as out_file: # change file name for PNG images
shutil.copyfileobj(response.raw, out_file)
else:
print('Error: ' + response.text)
newwin = Toplevel(root)
ncanvas = Canvas(newwin, width=500, height=500)
canvas.pack(fill="both", expand=True)
my_image = PhotoImage(file='label.png')
display = canvas.create_image(850, 50, anchor=NE, image=my_image)
line = canvas.create_line(0, 0, 0, 0)
display.pack()
root.mainloop()
def click_limpiar():
Alto.delete(0.0, END)
Ancho.delete(0.0, END)
ParamString.delete(0.0, END)
TemplateLabel.delete(0.0, END)
def close_window():
root.destroy()
exit()
#Crear un label
Label (text="Ingresar ParamString: ") .place(x=10,y=15)
Label (text="Ingresar Tamaño (pulgadas): ") .place(x=10,y=160)
Label (text="Ingresar TemplateLabel: ") .place(x=10,y=218)
#Crear un textbox
ParamString = Text(root)
ParamString.pack()
ParamString.place(x=12, y=50, height=100, width=400)
Alto = Text(root)
Alto.pack()
Alto.place(x=12, y=190, height=20, width=20)
Ancho = Text(root)
Ancho.pack()
Ancho.place(x=52, y=190, height=20, width=20)
TemplateLabel = Text(root)
TemplateLabel.pack
TemplateLabel.place(x=12, y=250, height=300, width=400)
#Botones
Button(root, text="Aceptar", width=16, command=retrieve_input) .place(x=20,y=560)
Button(root, text="Limpiar", width=16, command=click_limpiar) .place(x=150,y=560)
Button(root, text="Salir", width=16, command=close_window) .place(x=280,y=560)
app = Window(root)
root.mainloop()
The Canvas part is this one:
newwin = Toplevel(root)
ncanvas = Canvas(newwin, width=500, height=500)
canvas.pack(fill="both", expand=True)
my_image = PhotoImage(file='label.png')
display = canvas.create_image(850, 50, anchor=NE, image=my_image)
line = canvas.create_line(0, 0, 0, 0)
display.pack()
Thanks in advance,

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

AttributeError User Questions object has no attribute

I have this section of code that is not working properly. Was wondering whether anyone could understand what is wrong with it?
import os
from tkinter import *
import time
import sys
root = Tk()
root.attributes("-fullscreen", True)
class User_Questions:
def __init__(self, master):
self.master = master
master.title("MIT")
global frame
frame = Frame(master)
frame.pack()
self.choosen_questions = []
self.choosen_answers = []
self.choosen_questions_file = open(os.path.expanduser("~/Desktop/Bradfield/Project/" + str(test_choice) + "/Questions.txt"))
self.choosen_answers_file = open(os.path.expanduser("~/Desktop/Bradfield/Project/" + str(test_choice) + "/Answers.txt"))
for line in self.choosen_questions_file:
self.new_question = line.replace("\n","")
self.choosen_questions.append(self.new_question)
for line in self.choosen_answers_file:
self.new_answer = line.replace("\n","")
self.choosen_answers.append(self.new_answer)
self.correct_answers = 0
self.question_label = Label(frame, text = self.choosen_questions[0].replace("1. ",""), font = "Helvetica", fg = "blue")
self.question_label.pack()
self.answer_entry = Entry(frame, text = "", font = "Helvetica")
self.answer_entry.pack()
self.answer_entry.bind('<Return>', self.question)
self.check_test_exists_button = Button(frame, text="SUBMIT", font = "Helvetica", command=self.question)
self.check_test_exists_button.pack()
self.back_button = Button(frame, text="GO BACK", font = "Helvetica", command=self.go_back)
self.back_button.pack()
self.quit_button = Button(frame, text="QUIT", font = "Helvetica", command=master.destroy)
self.quit_button.pack()
def question(self, event):
for i in range(1, len(self.choosen_questions)):
return(self.choosen_questions[i+1].replace(i+". ",""))
def go_back(self):
frame.destroy()
my_gui = User_Choose_Test(root)
This is the error that outputs:
AttributeError: 'User_Questions' object has no attribute 'question'
The indentation of question and go_back is incorrect. It needs to be un-indented one level.

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