0

My aim is to have a prompt go at the startup, and based on the entered integer, have those many canvases fit in the frame. The frame must have a fixed height (and so should the Canvases), but the width should vary depending on the size of the window and be distributed equally among the canvases.

This works well with upto 4 canvases, after which the canvases do not fit into the max window also.

Plus, why am I not able to see the 20-pixel empty gray frame above and below the canvases, since the height of the canvas is lesser than that of the frame?

from tkinter import *
from tkinter import simpledialog

b=[]
root = Tk()
no_of_players=simpledialog.askinteger(prompt="Enter here", title="No of participants")

status_frame=Frame(root, bg='gray', height=100)
status_frame.pack(fill=X)
for i in range(no_of_players):
    c=Canvas(status_frame,  bg="orange")
    b.append(c)
    b[i].pack(side=LEFT,fill=X, expand=True)
root.mainloop()

EDIT

from tkinter import *
from tkinter import simpledialog

b=[]
root = Tk()
no_of_players=simpledialog.askinteger(prompt="Enter here", title="No of participants")

status_frame=Frame(root, bg='gray', height=500)
status_frame.pack(fill=X)
for i in range(no_of_players):
    c=Canvas(status_frame, width=1, height=100, bg="orange")
    b.append(c)
    b[i].pack(side=LEFT,fill=X, expand=True)
root.mainloop()
stochastic13
  • 423
  • 2
  • 15
  • I don't understand your question. You don't ever set the canvas width, so it defaults to something (378 pixels on my machine). What do you expect that it's not doing? – Novel Apr 11 '17 at 19:20
  • @Jonathan Something like suggested here in the second [asnwer](http://stackoverflow.com/questions/22835289/how-to-get-tkinter-canvas-to-dynamically-resize-to-window-width). I basically want the number of canvases to completely fill the frame in the X-direction, i.e. based on the number of canvases, they should divide the available frame width among them even on resizing the window. – stochastic13 Apr 11 '17 at 19:23
  • 1
    I recommend that you temporarily give `status_frame` a distinctive color so that you can see where its edges are. My guess is, they aren't where you think they are. – Bryan Oakley Apr 11 '17 at 20:44

1 Answers1

2

Canvases have a default size that they will try to be. Since windows and frames will attempt to grow or shrink to accommodate all their children, the main window grows when the default width times the number of canvases exceeds the window size.

The solution is pretty simple: give the canvases a small minimum width, then give the main window a preferred size, and let the canvases expand to fill the area.

For example:

...
root.geometry("400x100")
...
for i in range(no_of_players):
    c=Canvas(..., width=1)
    ...
...

As for why you don't see space above and below, it's because the default for pack is side='top', so it's going to try to stick to the top of the space it has been put in.

If you want space above and below, use pady, for example:

status_frame.pack(fill=x, pady=20)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • That perfectly solves the first problem. For the second: But I did specify `side=LEFT`. Moreover, even if it were top, if the height of the canvas is lower than that of the frame it set in, should not there be a blank space by default? – stochastic13 Apr 11 '17 at 20:22
  • @SatwikPasani: yes, you specified `side=LEFT` for the canvases. I'm not sure what point you're making. `side=LEFT` is definitely what you should do in this specific case. If the canvas is less tall than the window, there will be blank space below, but not above. Again, you specified "TOP", so it gets put at the top. – Bryan Oakley Apr 11 '17 at 20:30
  • I am sorry if I wasn't clear. When the height of the frame is set at say 500, and that of the canvas at 150, with side=LEFT while packing the canvas, there should be some empty frame left. I am unable to see it. Should I post something else to clarify the problem? The EDIT in the question. – stochastic13 Apr 11 '17 at 20:35
  • @SatwikPasani: note that when you set the height on a frame, and then put widgets in that frame, the frame will shrink or grow to fit the windows. 99.99% of the time this is what you want. It's unclear if you expect the frame to be 500 pixels tall, or if you want the window 500 pixels tall, or both to be 500 pixels tall. – Bryan Oakley Apr 11 '17 at 20:42
  • I want the frame to stay 500 pixel tall. Do I need to specify anything extra to achieve that? (Out of an academic interest. For the project, fitting is fine) – stochastic13 Apr 11 '17 at 20:45
  • @SatwikPasani: what's the point of making it 500 pixels tall? Are you certain the requirement is "make it 500 pixels tall", or do you think that forcing it to be 500 pixels tall will help you meet some other requirement? Is it really a requirement that the frame be 500 pixels tall, or just that the whole window be 500 pixels tall? – Bryan Oakley Apr 11 '17 at 21:03
  • @SatwikPasani: if you need the inner frame 500 pixels tall, and you need 20 pixels above and below the canvases, the simple solution is to make the canvases 460 pixels tall. – Bryan Oakley Apr 11 '17 at 21:05
  • I guess the issue can be solved by setting the padx or pady parameters. Was merely interested as a learning objective. Thanks anyway! Just to clarify, since frames fit into the dimensions of the widgets wrapped inside, the point of setting a height of the frame makes sense only if the frame is empty? – stochastic13 Apr 11 '17 at 21:10
  • @SatwikPasani: usually. You can force a frame to a specific size (search for "pack_propagate") but it rarely is the right thing to do because your UI may not work well on different systems or with different fonts, or when the user resizes the window. You can also switch to using `grid` where you can set a minsize. Or use `place` which lets you specify everything with pixel precision. The problem with the questions you're asking is that they are very hard to answer in a general way. – Bryan Oakley Apr 11 '17 at 21:31