3

Fairly new to Tkinter. I've looked in numerous posts about this issue, but none fixed it for me. I'm trying to create a simple GUI, in which I have a canvas which displays an image. The canvas is scrollable, but the scrollbars won't stretch to the size of the canvas.

Following is the relevant part of my code. there is no code here actually displaying the image, the image is given by an openFileDialog, but the scrollbars remain the same with the image.

from Tkinter import * import Image import ImageTk import numpy as np import tkFileDialog import os as os class DIP(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.isOpenedYet = False def initUI(self): self.parent.title("Viewer") self.pack(fill = BOTH, expand = 1) menubar = Menu(self.parent) self.parent.config(menu = menubar) vsframe = Frame(self, width=500, height=500) vsframe.grid(row = 1, column = 2, columnspan = 2, sticky = "nw") hsframe = Frame(self, width=500, height=500) hsframe.grid(row = 2, column = 1, rowspan = 2, sticky = "nw") self.canv = Canvas(self, relief=SUNKEN) self.canv.config(width=500, height=500) self.canv.config(highlightthickness=0) self.sbarV = Scrollbar(vsframe, orient=VERTICAL) self.sbarH = Scrollbar(hsframe, orient=HORIZONTAL) self.sbarV.config(command=self.canv.yview) self.sbarH.config(command=self.canv.xview) self.canv.config(yscrollcommand=self.sbarV.set) self.canv.config(xscrollcommand=self.sbarH.set) self.sbarV.pack(expand = YES, fill=BOTH) self.sbarH.pack(expand = YES, fill=BOTH) self.label2 = Label(self, border = 5) self.label2.grid(row = 0, column = 1) self.canv.grid(row = 1, column = 1, sticky = "nw") #Open Image Menu fileMenu = Menu(menubar) fileMenu.add_command(label = "Open", command = self.onOpen) menubar.add_cascade(label = "File", menu = fileMenu) #menu for algorithms basicMenu = Menu(menubar) basicMenu.add_command(label = "Super Resolution-stub", command = self.SuperRes) menubar.add_cascade(label = "Algorithms", menu = basicMenu) 

What am I missing?

2 Answers 2

2

There are a couple things that are going on here.

First, you don't need to put the scrollbars in separate frames. They can (and normally should) go in the same frame as the canvas.

Second, your scroll frames don't have the right "sticky" values. A vertical scrollbar needs to "stick" to both the top and bottom of the area it is given, and a horizontal one needs to "stick" to the left and right of the area it is given. Also, your canvas should "stick" to all sides of its area so that it fills the area.

Third, you aren't giving any weights to your rows and columns, so they don't resize the way you might expect. In your case, you want to give the row and column that contains the canvas a weight of 1 (one), so it takes up all of the extra space in the GUI.

Taking all that advice together, here's how to possibly get what you are wanting:

def initUI(self): self.parent.title("Viewer") self.pack(fill = BOTH, expand = 1) menubar = Menu(self.parent) self.parent.config(menu = menubar) self.grid_rowconfigure(1, weight=1) self.grid_columnconfigure(1, weight=1) self.canv = Canvas(self, relief=SUNKEN) self.canv.config(width=500, height=500) self.canv.config(highlightthickness=0) self.sbarV = Scrollbar(self, orient=VERTICAL) self.sbarH = Scrollbar(self, orient=HORIZONTAL) self.sbarV.config(command=self.canv.yview) self.sbarH.config(command=self.canv.xview) self.canv.config(yscrollcommand=self.sbarV.set) self.canv.config(xscrollcommand=self.sbarH.set) self.sbarV.grid(row=1, column=2, sticky="ns") self.sbarH.grid(row=2, column=1, sticky="ew") self.label2 = Label(self, border = 5, text="label 2") self.label2.grid(row = 0, column = 1) self.canv.grid(row = 1, column = 1, sticky = "nsew") ... 

By the way, here's a tip for debugging problems like this: give each "large" widget (frames, canvases, text widgets) a distinctive background color during development. For example, give "self" a background of blue, the canvas a background of pink, and so on. It becomes much easier to see where each item is going and how they resize relative to each other. Without this, it can sometimes be hard to know if some white space on the screen belongs to the main window, a child window, etc.

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

1 Comment

Thanks, sovled it already with petem's help, but your answer is exactly what I did, so thanks. Definitely going to use the bg color tip..
0

You don't need a frame for your scrollbars. Remove those and add the scrollbars to the Canvas widget:

self.sbarV = Scrollbar(self.canv, orient=VERTICAL) self.sbarH = Scrollbar(self.canv, orient=HORIZONTAL) 

Then, use .grid() for your scrollbars. It's not a good idea to mix pack and grid. Use the sticky option in your grid to sticky the scrollbars to the extent of the Canvas.

self.sbarV.grid(column=1, sticky=N+S) self.sbarH.grid(row=1, sticky=E+W) 

Doing that should fix it, everything else looks right.

More: http://effbot.org/zone/tkinter-scrollbar-patterns.htm

4 Comments

Thanks for the reply. I tried it before, but then the canvas shrinks to match the scrollbars, sticking to the NW corner...
I don't think it's a good idea to embed the scrollbars in the canvas -- anything you draw on the canvas might end up under the scrollbar. Also, the way the OP mixes pack and grid is perfectly fine. You can (and should!) mix them in an app, just not in the same widget.
Finally got it! I passed self to the scrollbars instead of self.canvas. Thanks for the pointers in the direction.
Good call. Yonadav, here's a good reference for exactly what you're trying to do: stackoverflow.com/questions/7727804/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.