Tkinter Canvas/Grid question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gary Richardson

    Tkinter Canvas/Grid question

    Is there a simple way of causing the size of a canvas to change as the
    window is resized when using the Grid geometry manager? Setting
    sticky='NESW', as in the following code, doesn't work though the
    documentation for Grid seems to imply that it should: "sticky If a
    slave's cell is larger than its requested dimensions, this option may be
    used to position (or stretch) the slave within its cell. ... The sticky
    option subsumes the combination of anchor and fill that is used by
    pack". Or is there something wrong with my code?

    Thanks,
    Gary Richardson

    from Tkinter import *

    class Test(Frame):
    def __init__(self, parent):
    Frame.__init__( self, parent)
    frame = Frame(parent)
    self.canvas = Canvas(frame, bg='white' , width=300, height=100)
    self.canvas.gri d(row=0, column=0, sticky='NESW')
    frame.grid()

    root = Tk()
    Test(root)
    root.mainloop()





  • Michael Peuser

    #2
    Re: Tkinter Canvas/Grid question

    Hi Gary
    [color=blue]
    > from Tkinter import *
    >
    > class Test(Frame):
    > def __init__(self, parent):
    > Frame.__init__( self, parent)
    > frame = Frame(parent)[/color]

    There is some confusion here: self *is* the frame, no need or use to make
    another....
    [color=blue]
    > self.canvas = Canvas(frame, bg='white' , width=300, height=100)[/color]

    There is some trick needed here: add:
    self.rowconfigu re(0, weight=1)
    self.columnconf igure(0, weight=1)
    [color=blue]
    > self.canvas.gri d(row=0, column=0, sticky='NESW')
    > frame.grid()[/color]
    This packs the frame to the parent, so it limits the size of your frame in
    any case
    I should recommend pack in this place (which is possible, because it's
    another frame)

    Altogether it shall look as follows and work fine:

    def __init__(self, parent):
    Frame.__init__( self, parent)
    self.pack(fill= BOTH,expand=1)

    self.canvas = Canvas(self, bg='white' , width=300, height=100)
    self.rowconfigu re(0, weight=1)
    self.columnconf igure(0, weight=1)
    self.canvas.gri d(row=0, column=0, sticky='nesw')



    Comment

    • Jeff Epler

      #3
      Re: Tkinter Canvas/Grid question

      To expand on Michael Peuser's response, I'll explain a little more. The
      grid first calculates the size requested by each item to find the
      requested size for each row and column. When there are no rowspans,
      the requested size for a row is the maximum of the requested sizes for
      any item in that row. The same holds when talking about columns, their
      weights and their widths.

      Then, when there is too much or too little space, the difference is
      split up among the rows according to their weight. The default weight
      for a row is 0. Let total_weight be the sum of the weight of each row
      with a widget, and diff be the number of pixels difference between the
      height of the frame and the sum of the requested heights of its rows. If
      total_weight is 0, then all rows get their requested height. Otherwise,
      each row gets diff*row_weight/total_weight, with something done about
      the rounding errors.

      That's why the short answer to set the weight of row and column 0 to 1
      works.

      The other problem you may run into (I haven't run your code, but with
      many levels of widget present, this may be a problem) is that each
      level of the widget tree between this one containing the canvas, and the
      Toplevel() or Tk() above it, must also be configured so that they will
      expand to consume any extra available space. Otherwise, the condition
      "when there is too much or too little space" can't be true, because the
      widget won't be given a larger size than it requested.

      Jeff

      Comment

      • Michael Peuser

        #4
        Re: Tkinter Canvas/Grid question


        "Jeff Epler" <jepler@unpytho nic.net>

        Thank you for the comprehensive explanations you gave I was to lazy to do
        ;-)
        In addition I should like to point out a chapter from Nancy Walsh's book
        "Learning Perl/Tk" where one can find a lot of information about the
        different geometry managers (no prejudices against Perl I hope?)

        [color=blue]
        > The other problem you may run into (I haven't run your code, but with
        > many levels of widget present, this may be a problem) is that each
        > level of the widget tree between this one containing the canvas, and the
        > Toplevel() or Tk() above it, must also be configured so that they will
        > expand to consume any extra available space[/color]

        This had been one of the problems, so I suggested to use an appropriate
        paramtrized pack on the higher level for simplicity.

        Kindly
        Michael P


        Comment

        • Gary Richardson

          #5
          Re: Tkinter Canvas/Grid question

          "Michael Peuser" <mpeuser@web.de > wrote in message
          news:bjp90r$1ng $07$1@news.t-online.com...
          [snip]


          Michael, Jeff,

          Thanks for your replies. I made the changes indicated above and the resizing
          works just fine now. I'm still puzzled as to why pack() would be used with
          the frame and grid() used with the canvas, and other widgets, I suppose. I
          was under the impression that only a single geometry manager should be used
          in a program. I guess the rule is: a single geometry manager must be used
          within a frame and its descendants. Is that correct?

          Thanks,
          Gary Richardson






          Comment

          • Michael Peuser

            #6
            Re: Tkinter Canvas/Grid question


            "Gary Richardson" <garyr@fidalgo. net>[color=blue]
            > Michael, Jeff,
            >
            > Thanks for your replies. I made the changes indicated above and the[/color]
            resizing[color=blue]
            > works just fine now. I'm still puzzled as to why pack() would be used with
            > the frame and grid() used with the canvas, and other widgets.[/color]

            No, no! I just use pack() because it is much simpler and you made no
            constraints as to how to show the frame in the toplevel.. There is a lot of
            useful information in that chapter from Nacy Welsh's book

            ......[color=blue]
            > was under the impression that only a single geometry manager should be[/color]
            used[color=blue]
            > in a program. I guess the rule is: a single geometry manager must be used
            > within a frame and its descendants. Is that correct?[/color]

            Nearly. You can freely choose the g.m. in EVERY frame (but then stick to it
            in THAT frame)

            Kindly
            Michael P




            Comment

            • Jeff Epler

              #7
              Re: Tkinter Canvas/Grid question

              > "Gary Richardson" <garyr@fidalgo. net>[color=blue][color=green]
              > > Michael, Jeff,
              > >
              > > Thanks for your replies. I made the changes indicated above and the[/color]
              > resizing[color=green]
              > > works just fine now. I'm still puzzled as to why pack() would be used with
              > > the frame and grid() used with the canvas, and other widgets.[/color][/color]

              You can manage any widget with any geometry manager. (You can even grid
              a button inside of a label, but god knows why you'd want to)

              Sometimes you must use "grid" to get proper layout. For instance, if
              you want to create a scrolled item (canvas or text) with horizontal and
              vertical scrollbars, this is the only sane way to do it.

              Comment

              Working...