tkinter text width

Discussion in 'Python' started by James Stroud, Apr 27, 2005.

  1. James Stroud

    James Stroud Guest

    Hello All,

    I would like for a tkinter text widget to be aware of how big the frame that
    contains it is, then I would like for it to reset its width to the
    appropriate number of characters when this frame changes size.

    I can get a cget("width") for the text, but this does not dynamically reflect
    the visible width.

    One way I can think of is getting the size of the font used in the widget then
    getting the width of the frame with cget then doing the appropriate math and
    configuring the text widget upon resize events.

    I'm thinking that there must be a more straightforward way.

    Any ideas?

    James


    --
    James Stroud
    UCLA-DOE Institute for Genomics and Proteomics
    Box 951570
    Los Angeles, CA 90095

    http://www.jamesstroud.com/
     
    James Stroud, Apr 27, 2005
    #1
    1. Advertising

  2. James Stroud

    Eric Brunel Guest

    On Tue, 26 Apr 2005 17:01:46 -0700, James Stroud <> wrote:

    > Hello All,
    >
    > I would like for a tkinter text widget to be aware of how big the frame that
    > contains it is, then I would like for it to reset its width to the
    > appropriate number of characters when this frame changes size.


    Errr... This is supposed to be the regular behaviour. How do you create your Text widget? Do you specify a width and height? If you do not, the default width and height are 80 and 24 respectively, and the widget won't resize to less than that. If you want a Text widget to be the smallest as possible in its container, you can do something like:

    -----------------------------------------------------
    from Tkinter import *

    root = Tk()

    t = Text(root, width=1, height=1)
    t.pack(fill=BOTH, expand=1)

    root.geometry('500x200')

    root.mainloop()
    -----------------------------------------------------

    The "trick" is to create the Text as small as possible (width=1, height=1), make it fill its whole container (pack(fill=BOTH, expand=1)), then set the dimensions for the container window (geometry('500x200')). You'll get a Text that will shrink and expand as much as you like.

    Is it what you were after?

    HTH
    --
    python -c "print ''.join([chr(154 - ord(c)) for c in 'U(17zX(%,5.zmz5(17;8(%,5.Z65\\'*9--56l7+-'])"
     
    Eric Brunel, Apr 27, 2005
    #2
    1. Advertising

  3. James Stroud

    James Stroud Guest

    On Wednesday 27 April 2005 02:31 am, so sayeth Eric Brunel:
    > The "trick" is to create the Text as small as possible (width=1, height=1),
    > make it fill its whole container (pack(fill=BOTH, expand=1)), then set the
    > dimensions for the container window (geometry('500x200')). You'll get a
    > Text that will shrink and expand as much as you like.
    >
    > Is it what you were after?


    This is more or less what I would like, but I would also like to probe the
    Text to see how many characters it thinks it can display within the container
    window. I am formatting text dynamically and so I rely on the width. I am not
    after the built in "wrap" option, it does not do what I want. But, say if
    wrap were turned on, it would be good to know how many characters the Text
    would wrap at.

    James

    --
    James Stroud
    UCLA-DOE Institute for Genomics and Proteomics
    Box 951570
    Los Angeles, CA 90095

    http://www.jamesstroud.com/
     
    James Stroud, Apr 27, 2005
    #3
  4. On Wed, 27 Apr 2005 10:52:14 -0700, James Stroud wrote:
    > This is more or less what I would like, but I would also like to probe the
    > Text to see how many characters it thinks it can display within the container
    > window. I am formatting text dynamically and so I rely on the width. I am not
    > after the built in "wrap" option, it does not do what I want. But, say if
    > wrap were turned on, it would be good to know how many characters the Text
    > would wrap at.


    I have extensive experience with trying to get text containers to do this.
    It is not easy. You have two choices:

    1. Give up. You can't tell anyhow if you're using a proportional font.

    2. Use a fixed-width font and manually wrap. (It's pretty easy then, you
    can ask the font for how wide any char is and do the math from there.)

    I have 70 line function that tries to replicate the Tk wrapping algorithm
    in the proportional text case, and it *still* doesn't work. For one thing,
    I actually found some bugs in the wrapping code (if a Unicode character
    gets into just the right position, it can actually run off the right end
    of the text widget, even if the widget is being wrapped), so completely
    matching the layout seems infeasible.

    I would strongly, strongly suggest finding another way to do what you are
    trying to do. I have blown many, many hours on this problem, and I found
    no simple logic. The edge cases kill you; while Tk is consistent (same
    text, same wrap every time), sometimes it wraps a word if it goes up to
    the edge, sometimes if it's one pixel off, damned if I can find a pattern
    (probably has something to do with trying to space the letters out,
    kerning or one of its simpler friends), and it probably changes
    periodically anyhow... and note based on this I can't even guarantee #2
    above, if you get unlucky.

    Basically, I'm pretty sure you can't do this.
     
    Jeremy Bowers, Apr 27, 2005
    #4
  5. James Stroud

    James Stroud Guest

    Thank you to everybody helping me. I think I am almost there...

    On Wednesday 27 April 2005 12:10 pm, so sayeth Jeremy Bowers:
    > 2. Use a fixed-width font and manually wrap. (It's pretty easy then, you
    > can ask the font for how wide any char is and do the math from there.)


    How might I query the size of a fixed-width font in pixles? It appears that
    the width of the font in points does not correlate with its width in pixels
    based on some simple expriments I have done. Using cget("font") on the Text
    gives back a string with the point size.

    > [snip some things to worry about]
    > Basically, I'm pretty sure you can't do this.


    My setup is not very complicated, so I don't think I have to worry about
    kerning, unicode, etc.. I am using a fixed width font (courier) only, and
    only one size and am also quite comfortable with giving away several pixels
    at the end of a line for "rounding errors" and will filter for a limited
    alphabet consisting only of the numbers, the captial letters, and the space.

    I think I can do this given these limitations.

    James

    --
    James Stroud
    UCLA-DOE Institute for Genomics and Proteomics
    Box 951570
    Los Angeles, CA 90095

    http://www.jamesstroud.com/
     
    James Stroud, Apr 27, 2005
    #5
  6. On Wed, 27 Apr 2005 12:52:21 -0700, James Stroud wrote:

    > Thank you to everybody helping me. I think I am almost there...
    >
    > On Wednesday 27 April 2005 12:10 pm, so sayeth Jeremy Bowers:
    >> 2. Use a fixed-width font and manually wrap. (It's pretty easy then, you
    >> can ask the font for how wide any char is and do the math from there.)

    >
    > How might I query the size of a fixed-width font in pixles? It appears that
    > the width of the font in points does not correlate with its width in pixels
    > based on some simple expriments I have done. Using cget("font") on the Text
    > gives back a string with the point size.


    Ah, in that case you want the measure attribute of the font object.

    http://www.pythonware.com/library/tkinter/introduction/x4671-methods.htm

    >
    >> [snip some things to worry about]
    >> Basically, I'm pretty sure you can't do this.

    >
    > My setup is not very complicated, so I don't think I have to worry about
    > kerning, unicode, etc.. I am using a fixed width font (courier) only, and
    > only one size and am also quite comfortable with giving away several pixels
    > at the end of a line for "rounding errors" and will filter for a limited
    > alphabet consisting only of the numbers, the captial letters, and the space.
    >
    > I think I can do this given these limitations.


    Sounds like it.

    What I did was set up unit test that threw random snippets at the text
    widget, and compared how many lines my code thought the widget should
    have, vs. what the widget claimed to have. This is how I discovered that
    some unicode was wrapped incorrectly. You can get what the widget claims
    to have by asking it for the geometric position of the last character with
    the bbox method of the Text widget.

    This is, however, probably not the answer you are looking for, because you
    only get a bounding box if the text is currently visible on the screen.
    This makes it fairly difficult to use to ask the widget *how far* off the
    screen the text is. If it were that easy I would have said so earlier
    :) But you may find that useful too, as you cobble together a solution.
     
    Jeremy Bowers, Apr 27, 2005
    #6
  7. James Stroud

    Eric Brunel Guest

    On Wed, 27 Apr 2005 12:52:21 -0700, James Stroud <> wrote:

    [snip]
    > How might I query the size of a fixed-width font in pixles? It appears that
    > the width of the font in points does not correlate with its width in pixels
    > based on some simple expriments I have done.


    This is the case on all platforms, but far more sensible on Windows: Windows attempts to be "clever" and corrects the font size you give depending on your screen resolution so that a 12 point font is supposed to be actually 12/72 inches *on screen* (obviously ignoring the fact that this is almost never what you want, since all other dimensions are in screen points by default...). Other platforms than Windows are supposed to do this too, but (fortunately) it seems to fail and the computed factor is very close to 1 (I got something like 1.04 on Linux, whatever the screen resolution was).

    To avoid this, you can try to use the winfo_* methods to get the screen resolution (I thought there was a more straightforward way, but the only way I see is to do someWidget.winfo_screenwidth() / someWidget.winfo_screenmmwidth(), with the usual adjustement to get inches instead of millimeters). You can then use this adjustement on all the dimensions you compute so that it will be consistent with the font sizes you get.

    The other solution is to turn the adjustement off. You can do this at tk level with the command "tk scaling 1". Unfortunately, this command does not seem to be directly available at Tkinter level, so you'll have to do:
    someWidget.tk.call('tk', 'scaling', 1)
    After doing that, all your font sizes should be in screen points. But be aware that *all* your fonts will seem to shrink (the screen resolutions these days are usually closer to 92 dpi than to 72...). So you may have to do some adjustements on other parts of your application (the biggest problem I got was with menu items).

    HTH
    --
    python -c "print ''.join([chr(154 - ord(c)) for c in 'U(17zX(%,5.zmz5(17;8(%,5.Z65\\'*9--56l7+-'])"
     
    Eric Brunel, Apr 28, 2005
    #7
  8. On Thu, 28 Apr 2005 10:36:18 +0200, "Eric Brunel"
    <> declaimed the following in comp.lang.python:

    > This is the case on all platforms, but far more sensible on Windows: Windows attempts to be "clever" and corrects the font size you give depending on your screen resolution so that a 12 point font is supposed to be actually 12/72 inches *on screen* (obviously ignoring the fact that this is almost never


    Pardon? Since when has Windows attempted to scale fonts for
    screen display based on screen resolution?

    The older Macs were fixed at 72 pixels per inch -- with the
    result that the /only/ way to increase the resolution was to physically
    change to a larger monitor. This is why they were so popular for DTP --
    the on-screen view WAS the same size as the printed view.

    Windows display properties defaults to an /assumed/ 96 pixels
    per inch regardless of the screen resolution (right-click the desktop
    background, properties, Settings/Advanced, General). This is why
    changing to a low-resolution (like the recovery mode screen on W98) on a
    large monitor results in such a pixilated, large-character, display.

    I'm currently running a 20" flat-panel at 1600x1200. It also
    appears to be about 12" vertical display region, making for
    100pixels/inch. If I set it to 800x600, it would be running at 50pixels
    per inch -- even though Windows is still assuming 96ppi for rendering. A
    12pt typeface would be just under 1/8" on normal, but 1/4" on the low
    resolution setting.

    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
     
    Dennis Lee Bieber, Apr 28, 2005
    #8
  9. James Stroud

    Eric Brunel Guest

    On Thu, 28 Apr 2005 16:14:02 GMT, Dennis Lee Bieber <> wrote:

    > On Thu, 28 Apr 2005 10:36:18 +0200, "Eric Brunel"
    > <> declaimed the following in comp.lang.python:
    >
    >> This is the case on all platforms, but far more sensible on Windows: Windows attempts to be "clever" and corrects the font size you give depending on your screen resolution so that a 12 point font is supposed to be actually 12/72 inches *on screen* (obviously ignoring the fact that this is almost never

    >
    > Pardon? Since when has Windows attempted to scale fonts for
    > screen display based on screen resolution?
    >
    > The older Macs were fixed at 72 pixels per inch -- with the
    > result that the /only/ way to increase the resolution was to physically
    > change to a larger monitor. This is why they were so popular for DTP --
    > the on-screen view WAS the same size as the printed view.
    >
    > Windows display properties defaults to an /assumed/ 96 pixels
    > per inch regardless of the screen resolution (right-click the desktop
    > background, properties, Settings/Advanced, General). This is why
    > changing to a low-resolution (like the recovery mode screen on W98) on a
    > large monitor results in such a pixilated, large-character, display.
    >
    > I'm currently running a 20" flat-panel at 1600x1200. It also
    > appears to be about 12" vertical display region, making for
    > 100pixels/inch. If I set it to 800x600, it would be running at 50pixels
    > per inch -- even though Windows is still assuming 96ppi for rendering. A
    > 12pt typeface would be just under 1/8" on normal, but 1/4" on the low
    > resolution setting.


    Sorry for that: my mistake. Anyway, the problem remains; the ouput for the "tk scaling" command on Windows and Linux is as follows:

    [Windows]
    % tk scaling
    1.33202228777

    [Linux]
    % tk scaling
    1.04285347703

    (all of this tested with tcl/tk 8.3 - Windows is Win2k, Linux is an old Mandrake 8.0).

    So this means that when you ask for a 12 point font, Windows will give you a 12 * 1.33202228777 = 16 screen pixels font and Linux a 12 * 1.04285347703 = 12 or 13 screen pixels font, depending on how the size is rounded. But the dimensions you set for all widgets are in screen pixels, unless explicitely given in another unit. So either you do a "tk scaling 1" at the beginning of all your apps, or you specify all widget diemnsions as '100p' instead of just 100 for example. If you don't do either, all your texts will look really bigger on Windows than on Linux.
    --
    python -c "print ''.join([chr(154 - ord(c)) for c in 'U(17zX(%,5.zmz5(17;8(%,5.Z65\\'*9--56l7+-'])"
     
    Eric Brunel, Apr 29, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. AndrewF
    Replies:
    1
    Views:
    787
    Bruce Barker
    Oct 10, 2005
  2. Xu
    Replies:
    11
    Views:
    8,571
    Andrew Thompson
    Jul 16, 2005
  3. Sean Jorden
    Replies:
    1
    Views:
    600
    laurie
    Aug 19, 2003
  4. Coder
    Replies:
    1
    Views:
    705
    Cowboy \(Gregory A. Beamer\)
    Jun 24, 2006
  5. Martin Franklin

    Re: tkinter text width

    Martin Franklin, Apr 27, 2005, in forum: Python
    Replies:
    0
    Views:
    436
    Martin Franklin
    Apr 27, 2005
Loading...

Share This Page