1

I am quite new to Tkinter, but, nevertheless, I was asked to "create" a simple form where user could provide info about the status of their work (this is sort of a side project to my usual work). Since I need to have quite a big number of text widget (where users are required to provide comments about status of documentation, or open issues and so far), I would like to have something "scrollable" (along the y-axis).

I browsed around looking for solutions and after some trial and error I found something that works quite fine. Basically I create a canvas, and inside a canvas a have a scrollbar and a frame. Within the frame I have all the widgets that I need.

This is a snipet of the code (with just some of the actual widgets, in particular the text ones):

from Tkinter import * ## My frame for form class simpleform_ap(Tk): # constructor def __init__(self,parent): Tk.__init__(self,parent) self.parent = parent self.initialize() # def initialize(self): # self.grid_columnconfigure(0,weight=1) self.grid_rowconfigure(0,weight=1) # self.canvas=Canvas(self.parent) self.canvas.grid(row=0,column=0,sticky='nsew') # self.yscrollbar = Scrollbar(self,orient=VERTICAL) self.yscrollbar.grid(column =4, sticky="ns") # self.yscrollbar.config(command=self.canvas.yview) self.yscrollbar.pack(size=RIGTH,expand=FALSE) # self.canvas.config(yscrollcommand=self.yscrollbar.set) self.canvas.pack(side=LEFT,expand=TRUE,fill=BOTH) # self.frame1 = Frame(self.canvas) self.canvas.create_window(0,0,window=self.frame1,anchor='nw') # Various Widget # Block Part # Label self.labelVariableIP = StringVar() # Label variable labelIP=Label(self.frame1,textvariable=self.labelVariableIP, anchor="w", fg="Black") labelIP.grid(column=0,row=0,columnspan=1,sticky='EW') self.labelVariableIP.set(u"IP: ") # Entry: Single line of text!!!! self.entryVariableIP =StringVar() # variable for entry field self.entryIP =Entry(self.frame1, textvariable=self.entryVariableIP,bg="White") self.entryIP.grid(column = 1, row= 0, sticky='EW') self.entryVariableIP.set(u"IP") # Update Button or Enter button1=Button(self.frame1, text=u"Update", command=self.OnButtonClickIP) button1.grid(column=2, row=0) self.entryIP.bind("<Return>", self.OnPressEnterIP) #... # Other widget here # # Some Text # Label self.labelVariableText = StringVar() # Label variable labelText=Label(self.frame1,textvariable= self.labelVariableText, anchor="nw", fg="Black") labelText.grid(column=0,row=curr_row,columnspan=1,sticky='EW') self.labelVariableTexta.set(u"Insert some texts: ") # Text textState = TRUE self.TextVar=StringVar() self.mytext=Text(self.frame1,state=textState, height = text_height, width = 10, fg="black",bg="white") # self.mytext.grid(column=1, row=curr_row+4, columnspan=2, sticky='EW') self.mytext.insert('1.0',"Insert your text") # # other text widget here # self.update() self.geometry(self.geometry() ) self.frame1.update_idletasks() self.canvas.config(scrollregion=(0,0, self.frame1.winfo_width(), self.frame1.winfo_height())) # def release_block(argv): # Create Form form = simpleform_ap(None) form.title('Release Information') # form.mainloop() # if __name__ == "__main__": release_block(sys.argv) 

As I mentioned before, this scripts quite does the work, even if, it has a couple of small issue that are not "fundamental" but a little annoying.

When I launch it I got this (sorry for the bad screen-capture): enter image description here

As it can be seen, it only shows up the first "column" of the grid, while I would like to have all them (in my case they should be 4) To see all of the fields, I have to resize manually (with the mouse) the window. What I would like to have is something like this (all 4 columns are there): enter image description here

Moreover, the scrollbar does not extend all over the form, but it is just on the low, right corner of the windows.

While the latter issue (scrollbar) I can leave with it, the first one is a little more important, since I would like to have the final user to have a "picture" of what they should do without needing to resize the windows.

Does any have any idea on how I should proceed with this? What am I missing?

Thanks in advance for your help

3
  • In your __init__, you do not appear to have set the size of your main window. You should do that, or it will just set the window to a default size, which will only show whatever it can, and in your case, only 1 column. Therefore, in the __init__ part of the class, try putting self.geometry(str(your_width) + "x" + str(your_height)) where your_width and your_height are whatever integers you choose that allow you to see what you need to in the window. Commented Feb 24, 2016 at 9:16
  • I will make this, including a solution to your second problem, an answer. Commented Feb 24, 2016 at 9:35
  • Thanks a lot! I manage to have it work and you made my day! I will wait for your final answer with also the second issue. Commented Feb 24, 2016 at 9:36

1 Answer 1

3

In the __init__ method of your class, you do not appear to have set the size of your main window. You should do that, or it will just set the window to a default size, which will only show whatever it can, and in your case, only 1 column. Therefore, in the __init__ method, try putting self.geometry(str(your_width) + "x" + str(your_height)) where your_width and your_height are whatever integers you choose that allow you to see what you need to in the window.

As for your scrollbar issue, all I had to do was change the way your scrollbar was added to the canvas to a .pack() and added the attributes fill = 'y' and side = RIGHT to it, like so:

self.yscrollbar.pack(side = 'right', fill = 'y') 

Also, you don't need:

self.yscrollbar.config(command=self.canvas.yview) self.yscrollbar.pack(size=RIGHT,expand=FALSE) 

Just add the command option to the creation of the scrollbar, like so:

self.scrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview) 

In all, the following changes should make your code work as expected:

  • Add:

    def __init__(self,parent): Tk.__init__(self,parent) self.parent = parent self.initialize() # Resize the window from the default size to make your widgets fit. Experiment to see what is best for you. your_width = # An integer of your choosing your_height = # An integer of your choosing self.geometry(str(your_width) + "x" + str(your_height)) 
  • Add and Edit:

    # Add `command=self.canvas.yview` self.yscrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview) # Use `.pack` instead of `.grid` self.yscrollbar.pack(side = 'right', fill = 'y') 
  • Remove:

    self.yscrollbar.config(command=self.canvas.yview) self.yscrollbar.pack(size=RIGHT,expand=FALSE) 
Sign up to request clarification or add additional context in comments.

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.