Skip to content

Getting width of Tk text widget via tcltk

8 messages · John Fox, Brian Ripley, Peter Dalgaard

#
Dear list members,

Is it possible via a suitable tcltk command to get the *current* width, in
characters, of a Tk text widget that has been resized with the mouse? In the
following code, the reported width of the text widget doesn't change, even
though it has been resized. I can, however, get the current width in pixels:
<Tcl>
<Tcl>
<Tcl>
<Tcl> 80
<Tcl> 486
<Tcl> 80
<Tcl> 743 

I could convert pixels to characters, but wonder whether I can get the
latter directly.

Any help would be appreciated.

John

--------------------------------
John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4
905-525-9140x23604
http://socserv.mcmaster.ca/jfox
#
On Mon, 28 Feb 2005, John Fox wrote:

            
I suspect you may have some difficulty with the latter, even in a 
monospace font.  Notice that 486 is not a multiple of 80, and if that is 
actually 81, 743 is not a multiple of 6.

I was trying to do this with heights for a listbox a few days ago, and it 
seems that the line spacing is actually 1 pixel greater than is reported. 
Since you can resize to a non-integer number of lines I don't believe (and 
I tried to read the source code) that Tcl/Tk works internally with 
characters.
#
Dear Brian,

As you guessed, I am using a monospaced font. I'll try the equivalent of
floor(743/(486/(80 + 1))) and see whether it's reliable. In particular,
thanks for the tip about the additional character (perhaps due to Tcl
0-based indexing?) -- a bit of experimentation shows that it's consistently
true.

Regards,
 John

--------------------------------
John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4
905-525-9140x23604
http://socserv.mcmaster.ca/jfox 
--------------------------------
#
Prof Brian Ripley <ripley@stats.ox.ac.uk> writes:
I think that's actually an issue that involves the window manager too.
I don't think all WMs know how to deal in integer number of
characters. 

Anyways, the following piece of Tcl seems to do the trick:

% expr ([winfo width .a] - 2 * [.a cget -borderwidth] - 4)/[font measure [.a cget -font] 0]
27

Converting to R is left as an exercise...

If I got it right then the point is that at either side of the window
you have by 1 pixel, n border pixels, and 1 spacer pixel before the
first character.
#
Dear Peter,

(as.numeric(tkwinfo("width", .output$ID))
    - 2*as.numeric(tkcget(.output, borderwidth=NULL)) - 2)/
    as.numeric(tkfont.measure(tkcget(.output, font=NULL), "0"))

(for the text widget .output) appears to do the trick (note, subtracting 2
rather than 4).

Thank you,
 John

--------------------------------
John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4
905-525-9140x23604
http://socserv.mcmaster.ca/jfox 
--------------------------------
#
"John Fox" <jfox@mcmaster.ca> writes:
Hmm, that's odd. I needed the 4. Beware that Tcl does integer division
(%/%). Did you round() or floor() the result?
#
Dear Peter,

As you can see from the expression, I didn't use integer division, nor did I
round() or floor(). Here's my original example, using a monospaced font:
+     font=tkfont.create(family="courier", size=10))
<Tcl>
<Tcl>
<Tcl>
<Tcl> 80
<Tcl> 646
+      - 2*as.numeric(tkcget(textWindow, borderwidth=NULL)) - 4) /
+      as.numeric(tkfont.measure(tkcget(textWindow, font=NULL), "0"))
[1] 79.75
+      - 2*as.numeric(tkcget(textWindow, borderwidth=NULL)) - 2) /
+      as.numeric(tkfont.measure(tkcget(textWindow, font=NULL), "0"))
[1] 80

I believe that the right answer is 80, and this appears correct visually,
confirmed by typing in the window.

My object was to be able to adjust R output to the width of the widget, and
I can now do this (actually, Brian's approach also worked well enough for
me).

Thank you again for your help.

John

--------------------------------
John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4
905-525-9140x23604
http://socserv.mcmaster.ca/jfox 
--------------------------------
#
"John Fox" <jfox@mcmaster.ca> writes:
Interesting...
<Tcl> 488
+      - 2*as.numeric(tkcget(textWindow, borderwidth=NULL)) - 4) /
+   as.numeric(tkfont.measure(tkcget(textWindow, font=NULL), "0"))
[1] 80
+       - 2*as.numeric(tkcget(textWindow, borderwidth=NULL)) - 2) /
+       as.numeric(tkfont.measure(tkcget(textWindow, font=NULL), "0"))
[1] 80.33333

Notice, btw, that textWindow$ID  shouldnn't be necessary.