3

Possible Duplicate:
Adding a scrollbar to a grid of widgets in Tkinter

On my project, i want do display my results in a window, using Tkinter as GUI. I place them in a kind of table, using the grid widget, and the window is separated in two different parts (for different results). But after longer runs, the number of results displayed exceed the height of my screen, so i want to add a scrollbar to my program. I already looked into several questions here on stackoverflow, and the answer that has come closest was this:

Adding a scrollbar to a group of widgets in Tkinter (just to let You know what I am axactly looking for!)

I am not able to apply that to my program though, maybe because I am rather new to Python and sometimes think i am a Dr. Frankenstein with tutorial-examples.

I tried a lot now, but i cant get the tables to be displayed in the canvas, possibly just some little thing i am missing.

I created an abstract example of my program (without scrollbar) so You know what I am working with, maybe someone of You can help my getting that scrollbar where it belongs!

Thank You very much!

example code: (runs)

import Tkinter as tk toprow=1 botrow=1 class ProgramWindow(tk.Frame): def __init__(self,name): self.name = name tk.Frame.__init__(self,root) self.pack() if name=="BotWin": tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1) elif name=="TopWin": tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1) def addrowTop(self,stuff,otherstuff): global toprow textfield = tk.Text(self,width=30,height=1) textfield.grid(row=toprow,column=0) textfield.insert('0.0',stuff) textfield = tk.Text(self,width=20,height=1) textfield.grid(row=toprow,column=1) textfield.insert('0.0',otherstuff) toprow+=1 def addrowBot(self,stuff,otherstuff): global botrow textfield = tk.Text(self,width=30,height=1) textfield.grid(row=botrow,column=0) textfield.insert('0.0',stuff) textfield = tk.Text(self,width=20,height=1) textfield.grid(row=botrow,column=1) textfield.insert('0.0',otherstuff) botrow+=1 def SomeProg(): for i in range(20): if i%2==0: stuff = "Stuff is "+str(i) otherstuff=i*3 Wins[0].addrowTop(stuff,otherstuff) elif i%2==1: stuff = "Stuff is "+str(i) otherstuff=i*4 Wins[1].addrowBot(stuff,otherstuff) root = tk.Tk() root.title("Stuff") Wins = [ ProgramWindow("TopWin"),ProgramWindow("BotWin")] SomeProg() root.mainloop() 

additional code with my tries to add the scrollbar (based on example shown in link above). if the scrollbar is only shown in the lower part, that would be okay since thats the part with the many results.)

import Tkinter as tk toprow=1 botrow=1 class ProgramWindow(tk.Frame): def __init__(self,name): self.name = name self.frame=tk.Frame.__init__(self,root) if name=="BotWin": tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1) self.canvas = tk.Canvas(root, borderwidth=0, 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) self.bind("<Configure>", self.OnFrameConfigure) elif name=="TopWin": self.pack() tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1) def addrowTop(self,stuff,otherstuff): global toprow textfield = tk.Text(self,width=30,height=1) textfield.grid(row=toprow,column=0) textfield.insert('0.0',stuff) textfield = tk.Text(self,width=20,height=1) textfield.grid(row=toprow,column=1) textfield.insert('0.0',otherstuff) toprow+=1 def OnFrameConfigure(self, event): self.canvas.configure(scrollregion=self.frame.bbox("all")) def addrowBot(self,stuff,otherstuff): global botrow textfield = tk.Text(self,width=30,height=1) textfield.grid(row=botrow,column=0) textfield.insert('0.0',stuff) textfield = tk.Text(self,width=20,height=1) textfield.grid(row=botrow,column=1) textfield.insert('0.0',otherstuff) botrow+=1 def SomeProg(): for i in range(20): if i%2==0: stuff = "Stuff is "+str(i) otherstuff=i*3 Wins[0].addrowTop(stuff,otherstuff) elif i%2==1: stuff = "Stuff is "+str(i) otherstuff=i*4 Wins[1].addrowBot(stuff,otherstuff) root = tk.Tk() root.title("Stuff") Wins = [ ProgramWindow("TopWin"),ProgramWindow("BotWin")] SomeProg() root.mainloop() 
5
  • 1
    Nothing to add to the wonderful answer and example provided in the question you linked. Take Brian Oakley's code and create your items in the so called populate method (or set the parent of your ProgramWindows to the embeded frame). You might have better feedback if you show us where you stuck / what have failed than what works... Commented Nov 8, 2012 at 15:25
  • i will edit/add the code with scrollbar, but it does not show what i wanted it to Commented Nov 8, 2012 at 15:36
  • i referred to it, applied it and it does not work for me, i can not figure out why. Commented Nov 8, 2012 at 16:06
  • 1
    difference I can see between Brian Oakley example and your's are: your ProgramWindow frame does not have the canvas as parent and OnFrameConfigure use self.frame scroll region and not self.canvas Commented Nov 8, 2012 at 16:13
  • i would like to have the the bottom-part in the canvas, the upper part can be the normal part. when you run the second code, you see that in the lower part there is a canvas window, i think i just mess up the part when i have to assing the frame to the canvas (thats why its white), and the scrollregion (thats why the scrollbar is unscrollable). i have trouble changing that :/ Commented Nov 8, 2012 at 16:21

2 Answers 2

4

To adapt Bryan Oakley's answer to your specific problem:

  • create your frame with the canvas as parent
  • use the canvas as the parameter of scrollregion

Note: when subclassing in python, you do not need to store the result of parent __init__ since it operate on self.

Here is the patch:

 def __init__(self,name): self.name = name - self.frame=tk.Frame.__init__(self,root) if name=="BotWin": + self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff") + tk.Frame.__init__(self,self.canvas) tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1) - self.canvas = tk.Canvas(root, borderwidth=0, 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) + self.canvas.create_window((4,4), window=self) self.bind("<Configure>", self.OnFrameConfigure) elif name=="TopWin": + self.frame=tk.Frame.__init__(self,root) self.pack() tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0) tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1) @@ -41,7 +40,7 @@ toprow+=1 def OnFrameConfigure(self, event): - self.canvas.configure(scrollregion=self.frame.bbox("all")) + self.canvas.configure(scrollregion=self.canvas.bbox("all")) def addrowBot(self,stuff,otherstuff): global botrow 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! i was trying around the time and my last result looked quite similar to yours, but i did not think of exchanging the 'frame' with 'canvas' in the OnFrameConfigure() that, and the create_window line were the only reasons i tried to store it, else i would have no self.frame (which i deperately tried to build in somehow) Thank you for the fix!
2

From your question I'm pretty sure I can help you, I had a similar problem a few months ago, and I tried so many different solutions, in the end I found out about the ttk treeview widget, from the ttk module, which comes standard with python 2.7

here is a small example to help you see what I mean

from Tkinter import * import ttk root = Tk() treedata = [('column 1', 'column 2'), ('column 1', 'column 2')] column_names = ("heading1", "heading2") tree = ttk.Treeview(root, columns = column_names, yscrollcommand = scrollbar.set) scrollbar = ttk.Scrollbar(root) scrollbar.pack(side = 'right', fill= Y) for x in treedata: tree.insert('', 'end', values =x) for col in column_names: tree.heading(col, text = col.Title()) scrollbar.config(command=tree.yview) tree.pack() 

hope this helps there isn't a lot of docs on this, but google will help, one very helpful link: http://www.tkdocs.com/tutorial/tree.html

good luck :)

3 Comments

Thats an interesting alternative, but unfortunately that does not fit my problem, since i just have two "groups" (i dont know a probper word, i am not that good at english), with one of tham containing too many "subentrys", and splitting them up is no alternative for me. I was considering to split them in several sections (once 20 lines were exceeded), but that did not turn out good for me. but thanks for that suggestion, that would be a good alternative for tabs!
surely you could use a while loop to check if its less than 20 rows, then if over 20 run a function to create a new treeview? If your'e only putting 20 in each, why do you need to scroll? are you trying to scroll individually or separately?
i would not need to scroll with treeview, but splitting the results after X rows is no option for me. if it was, treeview would be the way to go ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.