Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > tkinter text width

Reply
Thread Tools

tkinter text width

 
 
James Stroud
Guest
Posts: n/a
 
      04-27-2005
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/
 
Reply With Quote
 
 
 
 
Eric Brunel
Guest
Posts: n/a
 
      04-27-2005
On Tue, 26 Apr 2005 17:01:46 -0700, James Stroud <(E-Mail Removed)> 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+-'])"
 
Reply With Quote
 
 
 
 
James Stroud
Guest
Posts: n/a
 
      04-27-2005
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/
 
Reply With Quote
 
Jeremy Bowers
Guest
Posts: n/a
 
      04-27-2005
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.

 
Reply With Quote
 
James Stroud
Guest
Posts: n/a
 
      04-27-2005
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/
 
Reply With Quote
 
Jeremy Bowers
Guest
Posts: n/a
 
      04-27-2005
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/tk...71-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.

 
Reply With Quote
 
Eric Brunel
Guest
Posts: n/a
 
      04-28-2005
On Wed, 27 Apr 2005 12:52:21 -0700, James Stroud <(E-Mail Removed)> 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+-'])"
 
Reply With Quote
 
Dennis Lee Bieber
Guest
Posts: n/a
 
      04-28-2005
On Thu, 28 Apr 2005 10:36:18 +0200, "Eric Brunel"
<(E-Mail Removed)> 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 W9 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.

--
> ================================================== ============ <
> http://www.velocityreviews.com/forums/(E-Mail Removed) | Wulfraed Dennis Lee Bieber KD6MOG <
> (E-Mail Removed) | Bestiaria Support Staff <
> ================================================== ============ <
> Home Page: <http://www.dm.net/~wulfraed/> <
> Overflow Page: <http://wlfraed.home.netcom.com/> <

 
Reply With Quote
 
Eric Brunel
Guest
Posts: n/a
 
      04-29-2005
On Thu, 28 Apr 2005 16:14:02 GMT, Dennis Lee Bieber <(E-Mail Removed)> wrote:

> On Thu, 28 Apr 2005 10:36:18 +0200, "Eric Brunel"
> <(E-Mail Removed)> 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 W9 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+-'])"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Drop Down List Border Width vs Text Box Border Width Coder ASP .Net 1 06-24-2006 01:27 PM
Textbox width scaling to width of data not width of page? AndrewF ASP .Net 1 10-10-2005 04:38 PM
JComboBox width, dropdown list width Xu Java 11 07-15-2005 11:54 PM
Re: tkinter text width Martin Franklin Python 0 04-27-2005 06:50 AM
Re: resized image in table extends table width to original image width Sean Jorden HTML 1 08-19-2003 08:59 AM



Advertisments