2

I have a question about using the Tkinter Canvas object for making a GUI in Python.

When creating your frame object you give it the width and height you would like it to have. Is there a way to detect the size of it's container and use that for it's width and height?

For example lets say you wanted to created a Canvas that would always take up space equal to the entire Top Right Corner of the screen, even if your window was to be resized, or you were to use the Frame it's contained in in another program that maybe has another Frame taking up other screen space.

Take this for example:

import tkinter as tk

root = tk.Tk()
root.geometry("800x480")
container = tk.Frame(root, bg = "yellow")
container.pack(expand = True, fill = "both")
drawArea = tk.Canvas(container, bg = "red")
drawArea.pack()

In the above code the canvas will not take up the entirety of the yellow frame it is place in. I know if I want to set it to be the full size of the yellow frame I add expand = True, fill = "both" to the .pack() statement. However what if I only want it to be 2/3 of the Frame? Or half the width and height of the frame? Is it possible to do that?

Maybe I suck at Googling, but I can't seem to find any info on this online :\

Skitzafreak
  • 1,797
  • 7
  • 32
  • 51
  • Your language is a bit too vague. Can you post a [mcve] with some example code so we know what you are calling a container. It's unclear if you're talking about a frame in a canvas, or a canvas in a frame, or a canvas in a window, or something else. – Bryan Oakley Aug 02 '17 at 16:07
  • @BryanOakley sorry, just added a code snippet and hopefully that makes what I am asking a little clearer – Skitzafreak Aug 02 '17 at 16:34
  • @Skitzafreak: I think you are looking to resize the canvas based on the current window size. take a look at this [question/answer](https://stackoverflow.com/questions/22835289/how-to-get-tkinter-canvas-to-dynamically-resize-to-window-width) – Mike - SMT Aug 02 '17 at 17:03
  • You may have an [x/y](https://meta.stackexchange.com/a/66378/132201) problem here. Are you specifically asking how to get the width and height of a container, or is your real goal to configure the UI so that a container occupies some percentage of it's container (which can be done without knowing the width and height)? – Bryan Oakley Aug 02 '17 at 17:41
  • @BryanOakley I'm specifically asking how to make something like a Canvas, occupy only a portion of the container it is put inside of. – Skitzafreak Aug 02 '17 at 18:48

3 Answers3

2

In the code, when you are packing the canvas in the frame, set the "expand" keyword to True and the "fill" keyword to "both" (or tkinter.BOTH). If you are using a grid, then you need to use this code (taking the name "f" as the frame:

f.grid_rowconfigure(0, weight=1)
f.grid_columnconfigure(0, weight=1)

Then when you grid the canvas, set the "sticky" keyword to "nsew" (or tkinter.NSEW). In the code above, if you replace the 0's with the row and grid numbers that the canvas will be in, and the weight to whatever portion of the GUI that you want the canvas to fill. This should work.

  • This isn't exactly what I am trying to achieve. Even if you do `pack(expand = True, fill = "both")` the dimensions of the draw area on the Canvas don't seem to change. – Skitzafreak Aug 02 '17 at 16:48
2

In one of the comments you wrote:

I'm specifically asking how to make something like a Canvas, occupy only a portion of the container it is put inside of.

There are many ways to accomplish that. As you surmise, one way is to get the dimensions of the container, then set the dimensions of your widget accordingly.

You can also use geometry managers to manage this for you. For example, you could use grid to place the canvas in a specific row and column, and then arrange for that row and/or column to have exactly 1/4th of the container's height and/or width.

You could also use place instead of grid or pack. place is very good at sizing and placing widgets relative to other widgets. For example, you can set the relwidth to .25 to make the width of a widget be 1/4 the width of the parent.

Which choice is the right choice depends on many factors, mostly related to what other widgets are on the screen and how they should interact. Without knowing more details about your whole application rather than just one window, it's impossible to give more specific advice.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • So if I were to do something like `foo.grid_configure(relwidth = 0.25)` it would set the width of `foo` to be exactly 1/4 of it's container's width? – Skitzafreak Aug 02 '17 at 19:11
  • @Skitzafreak: no, because `grid` doesn't support `relwidth`. I see that I had a minor mistake in my answer. I've fixed that mistake. See http://effbot.org/tkinterbook/place.htm for how to use `place`. for `grid` it's a bit more complicated than a single configuration option. – Bryan Oakley Aug 02 '17 at 19:18
1

Took a little bit of guess work but I managed to accomplish what I was looking to do.

import tkinter as tk

root = tk.Tk()
container = tk.Frame(root, bg = "yellow")
container.pack(expand = true, fill = "both")
drawArea = tk.Canvas(container, bg = "red")
drawArea.update()
drawArea.configure(width = container.winfo_width(), height = winfo_height())
drawArea.pack()

The winfo_height and winfo_width contain the width and height of whatever you are using as the container for the canvas. So doing something like winfo_width / 2 will give you half the width of the container. However you need to update the canvas object first for the resizing to take effect.

Skitzafreak
  • 1,797
  • 7
  • 32
  • 51