0

I have the following code:

from win32com.client import Dispatch from tkinter import * from tkinter import ttk import tkinter class applicazione: def __init__(self, root): self.root = root self.root.title('Controllo dati per fatturazione elettronica - Manticle - Smith & Nephew Italia') ttk.Frame(self.root, width=300, height=250).pack() #### label list self.titoli = list() self.titoli_BFT = ["Num_Doc", "Cod_Art", "Unita Misura", "Tot_Prod", "Quant_Prod", "Perc_IVA_Prod", "Tot_IVA_Prod", "Linea_Prod", "Sconto", "Perc_Sconto", "Tipo_Sconto", "Cod_Art2", "Desc_Art"] self.titoli_HFT = ["Dest_Cod_FIS_P_Iva", "Cod_Cli", "Dest_RagSoc1", "Dest_RagSoc2", "Dest_Indirizzo", "Dest_CAP", "Dest_Localita", "Dest_Provincia", "Cli_Cod_Fis_P_Iva", "Cod_Dest", "Cli_RagSoc1", "Cli_RagSoc2", "Cli_Indirizzo", "Cli_CAP", "Cli_Localita", "Cli_Provincia", "Tipo_Doc", "pre_Num_Doc", "Num_Doc", "Data_Doc", "Vs_Rif", "Data_Rif", "Blank", "Blank2", "CPT", "Scad_Pagamento", "Descr", "Num_Ord", "Tot_Imp", "Tot_IVA", "Tot_Doc", "Nazione", "IPA", "Reg_Fiscale"] self.titoli_IVA = ["Num_Doc_TMP", "Num_Doc", "Imponibile", "IVA, Tot", "Perc_IVA"] self.titoli_RIF_DOC = [ "Num_Doc_TMP", "Num_Doc", "Rif_Doc" ] self.titoli_RIF_DOC_BFT = ["Num_Doc_TMP", "Num_Doc", "Cod_Art", "NOTE" ] self.titoli_anomalieBFT = ["ordine", "anomalia"] self.titoli_anomalieHFT = ["ordine", "anomalia"] self.inizializza_widgets() self.lettura() def inizializza_widgets(self): #label self.lblins=tkinter.Label(self.root, text="Controllo dati per fatturazione elettronica", font=("Helvetica", 12)) self.lblins.place(x=10, y=10 for i in range (0,len(self.titoli_HFT)): j = 80*i self.lblnome=tkinter.Label(self.root, text= self.titoli_HFT[i], font=("Helvetica", 8)) self.lblnome.place(x=85+j, y=50) #buttons ttk.Button(self.root, , text='Inserisci', width='10').place(x=645, y=590) #pulsante lettura ttk.Button(self.root, text='Modifica', width='10').place(x=725, y=590) ttk.Button(self.root, text='Indietro', width='10').place(x=805, y=590) ttk.Button(self.root, text='Avanti', width='10').place(x=885, y=590) def onFrameConfigure(self, event): '''Reset the scroll region to encompass the inner frame''' self.canvas.configure(scrollregion=self.canvas.bbox("all")) def lettura(self): xl= Dispatch("Excel.Application") xl.Visible = True self.checkb_intvar = list() #contiene una lista di 1 o 0 associati alle checkbox nella lista quadratini self.quadratiniB = l = [None] * (13 * len(self.titoli_BFT) ) self.quadratiniH = l = [None] * (13 * len(self.titoli_HFT) ) wbH = xl.Workbooks.Open(r'C:\Users\\Marco\\LAVORO\\Smith&Nephew\\appRonca\\fonte\\HFT_SAP_2.csv') print("wbH") wsH=wbH.WorkSheets(1) # get a reference to the first sheet cont = 0 MAX = 3 #13 lunghezza visibile senza barra navigatrice del numero di righe nella finestra 13 cont = 0 for i in range(0, MAX): for j in range(0,len(self.titoli_HFT)): print("for for") cont = cont + 1 print("i") print(i) print("j") print(j) print(" The {} set is often represented as {{0}} ".format("empty")) #### indexes for DI excel cells management k = 80*j #i con j l = 40*i #k con l contvalueX = i + 1 #con zero da errore allora +1 contvalueY = j + 1 #con zero da errore allora +1 self.txt1 = tkinter.Text(self.root, width='10', height='1') #Reading excel cells file if (wsH.Cells(contvalueX, contvalueY ).Value != None): self.txt1.insert('1.0', wsH.Cells(contvalueX, contvalueY ).Value)#ws.Cells(1,i).Value self.txt1.tag_add("start", "1.0", "1.13") if (contvalueY == 1 ): self.txt1.tag_config("start", background="white", foreground="red") #self.txt1.tag_configure("red", foreground="red") #self.txt1.highlight_pattern("word", "red") #self.txt1 = tkinter.Text(self.root, width='10', height='1', text = ws.Cells(1,i).Value) self.txt1.place(x=85+k, y=80+l) #5 + 80 print("if") else: #None case print("else") self.txt1.insert('1.0', "") self.txt1.place(x=85+k, y=80+l) if (contvalueY == 1 ): self.txt1.tag_config("start", background="white", foreground="red") wbH.Close() xl.Quit() if __name__ == '__main__': root = tkinter.Tk() w, h = root.winfo_screenwidth(), root.winfo_screenheight() root.geometry("%dx%d+0+0" % (w, h)) applicazione(root) root.mainloop() 

The application runned:

application image without scrollbar

I read data from an excel file (lettura function) but i would like to add an horizontal and a vertical scrollbar i read first of all this:

Adding a scrollbar to a group of widgets in Tkinter

but use "grid" that i do not use and i'm not able to associate my double "for" "Text" to the vertical scroll bar (Lettura function)

The following code is edited with the scrollbar but does not work:

import tkinter as tk from win32com.client import Dispatch from tkinter import * #from tkinter import ttk import tkinter class Example(tk.Frame): def __init__(self, root): tk.Frame.__init__(self, root) root.title('Controllo dati per fatturazione elettronica - Manticle - Smith & Nephew Italia') #tk.Frame(root, width=100, height=450).pack() self.canvas = tk.Canvas(root, borderwidth=0, background="#C0C0C0") self.frame = tk.Frame(self.canvas, background="#ffffff") self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview) self.canvas.configure(yscrollcommand=self.vsb.set) self.vsb.pack(side="right", fill="y") self.canvas.pack(side="left", fill="both", expand=True) self.canvas.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame") self.frame.bind("<Configure>", self.onFrameConfigure) self.titoli_BFT = ["Num_Doc", "Cod_Art", "Unita Misura", "Tot_Prod", "Quant_Prod", "Perc_IVA_Prod", "Tot_IVA_Prod", "Linea_Prod", "Sconto", "Perc_Sconto", "Tipo_Sconto", "Cod_Art2", "Desc_Art"] self.titoli_HFT = ["Dest_Cod_FIS_P_Iva", "Cod_Cli", "Dest_RagSoc1", "Dest_RagSoc2", "Dest_Indirizzo", "Dest_CAP", "Dest_Localita", "Dest_Provincia", "Cli_Cod_Fis_P_Iva", "Cod_Dest", "Cli_RagSoc1", "Cli_RagSoc2", "Cli_Indirizzo", "Cli_CAP", "Cli_Localita", "Cli_Provincia", "Tipo_Doc", "pre_Num_Doc", "Num_Doc", "Data_Doc", "Vs_Rif", "Data_Rif", "Blank", "Blank2", "CPT", "Scad_Pagamento", "Descr", "Num_Ord", "Tot_Imp", "Tot_IVA", "Tot_Doc", "Nazione", "IPA", "Reg_Fiscale"] #self.inizializza_widgets() self.populate() self.lettura() def inizializza_widgets(self): #label title self.lblins=tk.Label(root, text="Controllo dati per fatturazione elettronica", font=("Helvetica", 12)) self.lblins.place(x=10, y=10) for i in range (0,len(self.titoli_HFT)): j = 80*i self.lblnome=tk.Label(root, text= self.titoli_HFT[i], font=("Helvetica", 8)) self.lblnome.place(x=85+j, y=50) #965 560 tk.Button(root, text='Inserisci', width='10').place(x=645, y=590) #pulsante lettura tk.Button(root, text='Modifica', width='10').place(x=725, y=590) tk.Button(root, text='Indietro', width='10').place(x=805, y=590) tk.Button(root, text='Avanti', width='10').place(x=885, y=590) def lettura(self): xl= Dispatch("Excel.Application") xl.Visible = True wbH = xl.Workbooks.Open(r'C:\Users\\Marco\\LAVORO\\Smith&Nephew\\appRonca\\fonte\\HFT_SAP_2.csv') print("wbH") wsH=wbH.WorkSheets(1) # get a reference to the first sheet cont = 0 MAX = 9 #13 lunghezza visibile senza barra navigatrice del numero di righe nella finestra 13 cont = 0 for i in range(0, MAX): for j in range(0,len(self.titoli_HFT)): print("for for") cont = cont + 1 print("cont") print(cont) #### INDEXES k = 80*j #i con j l = 40*i #k con l contvalueX = i + 1 #con zero da errore allora +1 contvalueY = j + 1 #con zero da errore allora +1 self.txt1 = tk.Text(root, width='10', height='1') #Lettura celle del file HFT if (wsH.Cells(contvalueX, contvalueY ).Value != None): self.txt1.insert('1.0', wsH.Cells(contvalueX, contvalueY ).Value)#ws.Cells(1,i).Value self.txt1.tag_add("start", "1.0", "1.13") if (contvalueY == 1 ): self.txt1.tag_config("start", background="white", foreground="red") self.txt1.place(x=85+k, y=80+l) #5 + 80 print("if") else: #None case print("else") self.txt1.insert('1.0', "") self.txt1.place(x=85+k, y=80+l) if (contvalueY == 1 ): #### qui si richiama la funziona regole con tutte le regole self.txt1.tag_config("start", background="white", foreground="red") wbH.Close() xl.Quit() def onFrameConfigure(self, event): '''Reset the scroll region to encompass the inner frame''' self.canvas.configure(scrollregion=self.canvas.bbox("all")) if __name__ == "__main__": root=tk.Tk() Example(root).pack(side="top", fill="both", expand=True) root.mainloop() 

and this: How to add a scrollbar to a window with tkinter? that is not organise like a class.

how can i implement the 2 scrollbars?

UPDATE

new version:

from win32com.client import Dispatch from tkinter import * from tkinter import ttk import tkinter class applicazione: def __init__(self, root): self.root = root # Top-level frame self.frame = ttk.Frame(self.root, relief="sunken") # Canvas creation with double scrollbar hscrollbar = ttk.Scrollbar(self.frame, orient = tkinter.HORIZONTAL) vscrollbar = ttk.Scrollbar(self.frame, orient = tkinter.VERTICAL) self.canvas = tkinter.Canvas(self.frame, bd=0, highlightthickness=0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set) vscrollbar.config(command = self.canvas.yview) hscrollbar.config(command = self.canvas.xview) # Add controls here self.subframe = ttk.Frame(self.canvas) #Packing everything self.subframe.pack(padx = 15, pady = 15, fill = tkinter.BOTH, expand = tkinter.TRUE) hscrollbar.pack( fill=tkinter.X, side=tkinter.BOTTOM, expand=tkinter.FALSE) vscrollbar.pack( fill=tkinter.Y, side=tkinter.RIGHT, expand=tkinter.FALSE) self.canvas.pack(side = tkinter.LEFT, padx = 5, pady = 5, fill = tkinter.BOTH, expand= tkinter.TRUE) self.frame.pack( padx = 5, pady = 5, expand = True, fill = tkinter.BOTH) self.canvas.create_window(0,0, window = self.subframe) self.root.update_idletasks() # update geometry self.canvas.config(scrollregion = self.canvas.bbox("all")) self.canvas.xview_moveto(0) self.canvas.yview_moveto(0) self.root.title('Controllo dati per fatturazione elettronica - Manticle - Smith & Nephew Italia') ttk.Frame(self.root, width=300, height=250).pack() #### Titles self.titoli_HFT = ["Dest_Cod_FIS_P_Iva", "Cod_Cli", "Dest_RagSoc1", "Dest_RagSoc2", "Dest_Indirizzo", "Dest_CAP", "Dest_Localita", "Dest_Provincia", "Cli_Cod_Fis_P_Iva", "Cod_Dest", "Cli_RagSoc1", "Cli_RagSoc2", "Cli_Indirizzo", "Cli_CAP", "Cli_Localita", "Cli_Provincia", "Tipo_Doc", "pre_Num_Doc", "Num_Doc", "Data_Doc", "Vs_Rif", "Data_Rif", "Blank", "Blank2", "CPT", "Scad_Pagamento", "Descr", "Num_Ord", "Tot_Imp", "Tot_IVA", "Tot_Doc", "Nazione", "IPA", "Reg_Fiscale"] self.inizializza_widgets() def inizializza_widgets(self): self.lblins=tkinter.Label(self.root, text="Controllo dati per fatturazione elettronica", font=("Helvetica", 12)) self.lblins.place(x=10, y=10) for i in range (0,len(self.titoli_HFT)): j = 80*i self.lblnome=tkinter.Label(self.root, text= self.titoli_HFT[i], font=("Helvetica", 8)) self.lblnome.place(x=85+j, y=50) ttk.Button(self.root, text='Inserisci', width='10').place(x=645, y=590) ttk.Button(self.root, text='Modifica', width='10').place(x=725, y=590) ttk.Button(self.root, text='Indietro', width='10').place(x=805, y=590) ttk.Button(self.root, text='Avanti', width='10').place(x=885, y=590) if __name__ == '__main__': root = tkinter.Tk() root.title( "Double scrollbar with tkinter" ) w, h = root.winfo_screenwidth(), root.winfo_screenheight() root.geometry("%dx%d+0+0" % (w, h)) applicazione(root) root.mainloop() 
3
  • your code example doesn't run (is missing a populate function. Also, it doesn't even attempt to add a horizontal scrollbar. You say it "doesn't work" but what does that mean? You're not even attempting to add a horizontal scrollbar. What are you having trouble with? Making the scrollbar visible? Making it horizontal instead of vertical? Commented Jul 21, 2015 at 10:36
  • My issues are with lettura function and vertical scrollbar that i attempted to add in the second piece of code. I need horizontal and vertical scrollbar but i do not even to make visible the vertical scrollbar Commented Jul 22, 2015 at 15:39
  • Part of the problem seems to be that you're putting a frame inside the canvas, but you aren't putting anything inside the frame. So, the frame will have a size of 1x1. I can only guess if that's the only problem, since the code you presented doesn't run. Commented Jul 22, 2015 at 16:31

3 Answers 3

2

I've also struggled with creating a double scrollbar window. Here is an implementation using pack layout manager (you should be able to tailor it for a grid layout) :

import tkinter as tk from tkinter import ttk # Top-level frame root = tk.Tk() root.title( "Double scrollbar with tkinter" ) root.minsize(width = 600, height = 600) frame = ttk.Frame(root, relief="sunken") # Canvas creation with double scrollbar hscrollbar = ttk.Scrollbar(frame, orient = tk.HORIZONTAL) vscrollbar = ttk.Scrollbar(frame, orient = tk.VERTICAL) sizegrip = ttk.Sizegrip(frame) canvas = tk.Canvas(frame, bd=0, highlightthickness=0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set) vscrollbar.config(command = canvas.yview) hscrollbar.config(command = canvas.xview) # Add controls here subframe = ttk.Frame(canvas) #Packing everything subframe.pack(padx = 15, pady = 15, fill = tk.BOTH, expand = tk.TRUE) hscrollbar.pack( fill=tk.X, side=tk.BOTTOM, expand=tk.FALSE) vscrollbar.pack( fill=tk.Y, side=tk.RIGHT, expand=tk.FALSE) sizegrip.pack(in_ = hscrollbar, side = tk.BOTTOM, anchor = "se") canvas.pack(side = tk.LEFT, padx = 5, pady = 5, fill = tk.BOTH, expand= tk.TRUE) frame.pack( padx = 5, pady = 5, expand = True, fill = tk.BOTH) canvas.create_window(0,0, window = subframe) root.update_idletasks() # update geometry canvas.config(scrollregion = canvas.bbox("all")) canvas.xview_moveto(0) canvas.yview_moveto(0) # launch the GUI root.mainloop() 

(Tested with Python 3.4).

Exemples : enter image description here enter image description here

It's not perfect, since it lacks the small block on the bottom right corner.

UPDATE 1 : Added Sizegrip to get the bottom right resizing corner

UPDATE 2 : Added working solution to OP's updated code

from win32com.client import Dispatch from tkinter import * from tkinter import ttk import tkinter class applicazione(object): def __init__(self, root): self.root = root # Top-level frame self.root.title('Controllo dati per fatturazione elettronica - Manticle - Smith & Nephew Italia') self.frame = ttk.Frame(self.root, width=300, height=250) # Canvas creation with double scrollbar hscrollbar = ttk.Scrollbar(self.frame, orient = tkinter.HORIZONTAL) vscrollbar = ttk.Scrollbar(self.frame, orient = tkinter.VERTICAL) sizegrip = ttk.Sizegrip(self.frame) self.canvas = tkinter.Canvas(self.frame, bd=0, highlightthickness=0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set) vscrollbar.config(command = self.canvas.yview) hscrollbar.config(command = self.canvas.xview) # Add controls here self.subframe = ttk.Frame(self.canvas) #### Titles self.titoli_HFT = ["Dest_Cod_FIS_P_Iva", "Cod_Cli", "Dest_RagSoc1", "Dest_RagSoc2", "Dest_Indirizzo", "Dest_CAP", "Dest_Localita", "Dest_Provincia", "Cli_Cod_Fis_P_Iva", "Cod_Dest", "Cli_RagSoc1", "Cli_RagSoc2", "Cli_Indirizzo", "Cli_CAP", "Cli_Localita", "Cli_Provincia", "Tipo_Doc", "pre_Num_Doc", "Num_Doc", "Data_Doc", "Vs_Rif", "Data_Rif", "Blank", "Blank2", "CPT", "Scad_Pagamento", "Descr", "Num_Ord", "Tot_Imp", "Tot_IVA", "Tot_Doc", "Nazione", "IPA", "Reg_Fiscale"] self.inizializza_widgets() #Packing everything self.subframe.pack(fill = tkinter.BOTH, expand = tkinter.TRUE) hscrollbar.pack( fill=tkinter.X, side=tkinter.BOTTOM, expand=tkinter.FALSE) vscrollbar.pack( fill=tkinter.Y, side=tkinter.RIGHT, expand=tkinter.FALSE) sizegrip.pack(in_= hscrollbar, side = BOTTOM, anchor = "se") self.canvas.pack(side = tkinter.LEFT, padx = 5, pady = 5, fill = tkinter.BOTH, expand= tkinter.TRUE) self.frame.pack( padx = 5, pady = 5, expand = True, fill = tkinter.BOTH) self.canvas.create_window(0,0, window = self.subframe) self.root.update_idletasks() # update geometry self.canvas.config(scrollregion = self.canvas.bbox("all")) self.canvas.xview_moveto(0) self.canvas.yview_moveto(0) def inizializza_widgets(self): self.LabelFrame = ttk.Frame(self.subframe) self.lblins = tkinter.Label(self.LabelFrame, text="Controllo dati per fatturazione elettronica", font=("Helvetica", 12)) self.lblins.pack() for i in range (0,len(self.titoli_HFT)): j = 80*i self.lblnome=tkinter.Label(self.LabelFrame, text= self.titoli_HFT[i], font=("Helvetica", 8)) self.lblnome.pack(side = LEFT)#place(x=85+j, y=50) self.ContentFrame = ttk.Frame(self.subframe, width = 600, height = 600) self.ButtonsFrame = ttk.Frame(self.subframe) ttk.Frame(self.ButtonsFrame).pack(side=LEFT, fill = X, expand=TRUE) ttk.Button(self.ButtonsFrame, text='Inserisci', width='10').pack(side = LEFT) ttk.Button(self.ButtonsFrame, text='Modifica', width='10').pack(side = LEFT) ttk.Button(self.ButtonsFrame, text='Indietro', width='10').pack(side = LEFT) ttk.Button(self.ButtonsFrame, text='Avanti', width='10').pack(side = LEFT) ttk.Frame(self.ButtonsFrame).pack(side=RIGHT, fill = X, expand=TRUE) self.LabelFrame.pack(side = TOP, fill = X, expand=TRUE) self.ContentFrame.pack(fill = BOTH, expand = TRUE) self.ButtonsFrame.pack(side = BOTTOM, fill = X, expand = TRUE) if __name__ == '__main__': root = tkinter.Tk() root.title( "Double scrollbar with tkinter" ) w, h = root.winfo_screenwidth(), root.winfo_screenheight() root.geometry("%dx%d+0+0" % (0.99*w, 0.9*h)) applicazione(root) root.mainloop() 

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

I tried to implement your versione (i added a new version below UPDATE, at this line: for i in range (0,len(self.titoli_HFT)): self.lblnome=tkinter.Label(self.root, text= self.titoli_HFT[i], font=("Helvetica", 8)) if i put self.root, self.frame, self.subframe, self.canvas never view an active scrollbar!
The "small block in the corner" is provided by ttk.Sizegrip.
@patthoyts : thanks for the sizegrip tip. I didn't know that.
@user3798245 : there is a problem with your updated code. Tkinter has several layout managers : pack, place and grip. It is recommended to stick with only one. My solution use the packing layout whereas patthoyts use the grid one, and you use the place. I added a solution with the packing manager
1

Just to expand on the answer by @georgesl and demonstrate the use of the ttk sizegrip and also to show that grid works nicely for this kind of task, here is a short example showing a text widget with 2 scrollbars and the sizegrip in the corner.

# Demonstrate text widget with two scrollbars and the sizegrip. import tkinter as tk import tkinter.ttk as ttk root = tk.Tk() text = tk.Text(root) vs = ttk.Scrollbar(root, orient="vertical") hs = ttk.Scrollbar(root, orient="horizontal") sizegrip = ttk.Sizegrip(root) # hook up the scrollbars to the text widget text.configure(yscrollcommand=vs.set, xscrollcommand=hs.set, wrap="none") vs.configure(command=text.yview) hs.configure(command=text.xview) # grid everything on-screen text.grid(row=0,column=0,sticky="news") vs.grid(row=0,column=1,sticky="ns") hs.grid(row=1,column=0,sticky="news") sizegrip.grid(row=1,column=1,sticky="news") root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) def fill(): for n in range(30): text.insert("end", 'hello ' * 20, "", "\n") root.after(20, fill) root.mainloop() 

Comments

0

The process to add both a horizontal and vertical scrollbar to a collection of widgets is precisely the same as the solution provided in this answer: https://stackoverflow.com/a/3092341/7432. That answer shows only a vertical scrollbar, but adding a horizontal one is just a matter of a couple lines of code.

The solution is very straight-forward:

  • add widgets to a frame using whatever method you want
  • add the frame to a canvas using the create_window method of the canvas
  • add scrollbars to the canvas in the usual way
  • set the scrollregion attribute of the canvas to be big enough to incude the entire frame that was added
    • do this whenever you add or remove widgets from the frame
    • you might also need to do this whenever the canvas changes size

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.