Francisco Gracia | 2 Dec 2011 13:09
Picon

Syntactic problems

I am exploring the possibilities of using *Tkinter* for a serious application mainly devoted to the handling of pure text.
 
As en exercise I have tried to rewrite in *Python* an interesting example that is unusually included in the manual page of *Tk* for the *font* component (*Tcl8.5.7/Tk8.5.7 Documentation > TkCmd > font > example*); this code works fine under *tclsh* and *wish*. What is does is getting a list of the font names available in the machine in which it is running and displaying nicely each of its items with a sample of the corresponding font.
 
I have performed most of my purpose and my *Python* script works. Along the way have learned a lot about *Tkinter/Tk/Tcl*, which was also a desired goal of the exercise. But the script does not work completely well, as I have also hit against an obstacle that I do not know how to overcome and seems to be rather deep. It is the following:
 
Some of the names of the font families returned by the operating system (be it Windows or Linux) are composed of two or more words (like *Times New Roman CE*). Now these multiword arguments are not easily accepted by *Tcl/Tk*, especially if they are referenced by some variable, so that for instance tags cannot be reconfigured this way in order to apply such fonts; or the size of sentences using them cannot be measured, two operations that are essential for the procedure.
 
I have learned that this is a real and inherent difficulty with *Tcl* (Harrison and McLennan, *Effective Tcl/Tk programming*: 34, 66); this is why the original code uses such a strange syntax like
 
    .t tag configure f[incr count] -font [list $family 10]
 
The function *list* of *Tcl* seems to be mainly dedicated to solve this odd problem with the dereferencing of multiword contents of variables (*family* in this case, which holds the name of the font). But apparently this does not work when *Tcl/Tk* are finally moved by *Tkinter* during the execution of the script or at least I have been unable to find a way to make it work in due form.
 
Which does not mean much, as I am not a programmer or, at most, I am a very unseasoned one. Can somebody who has had the same problem and solved it succesfully from *Tkinter* offer me (and perhaps us) his insight and describe the essentials of how to do it?
 
Many thanks in advance!

_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Kevin Walzer | 2 Dec 2011 16:45
Favicon

Re: Syntactic problems

On 12/2/11 7:09 AM, Francisco Gracia wrote:

> Â
> Some of the names of the font families returned by the operating system
> (be it Windows or Linux) are composed of two or more words (like *Times
> New Roman CE*). Now these multiword arguments are not easily accepted by
> *Tcl/Tk*, especially if they are referenced by some variable, so that
> for instance tags cannot be reconfigured this way in order to apply such
> fonts; or the size of sentences using them cannot be measured, two
> operations that are essential for the procedure.

Multi-named fonts can be tricky.

> Â
> I have learned that this is a real and inherent difficulty with *Tcl*
> (Harrison and McLennan, *Effective Tcl/Tk programming*: 34, 66); this is
> why the original code uses such a strange syntax like
> Â
> Â Â Â  .t tag configure f[incr count] -font [list $family 10]
> Â
> The function *list* of *Tcl* seems to be mainly dedicated to solve this
> odd problem with the dereferencing of multiword contents of variables
> (*family* in this case, which holds the name of the font). But
> apparently this does not work when *Tcl/Tk* are finally moved by
> *Tkinter* during the execution of the script or at least I have been
> unable to find a way to make it work in due form.

I'm not quite clear on what problem you are experiencing here, as there 
are no code snippets or Python errors outlined.

Are you just trying to understand the underlying Tcl idioms?

In Tcl, the [list $family 10] converts the multi-named font into a 
single string that can be parsed by the font code. Tcl's [list] idiom is 
very handy for things like this.

I'm not sure about how the Tkinter module interacts with Tcl at that low 
level, but this Python code has always worked for me in displaying and 
selecting a font from a listbox:

        self.fonts=list(tkFont.families())
         self.fonts.sort()

         for item in self.fonts:
             self.fontlist.insert(END, item)

         newfontlist = list(self.fontlist.get(0, END))

         if self.fontname in newfontlist:
             i = newfontlist.index(self.fontname)
             self.fontlist.see(i)
             self.fontlist.select_set(i)
             self.fontlist.select_anchor(i)
         else:
             pass

(This code is partly based on code in IDLE. The code in idleib is a bit 
wooly, but snippets of it are quite useful for Tkinter samples.)

Hope this helps,
Kevin

> Â
> Which does not mean much, as I am not a programmer or, at most, I am a
> very unseasoned one. Can somebody who has had the same problem and
> solved it succesfully from *Tkinter* offer me (and perhaps us) his
> insight and describe the essentials of how to do it?
> Â
> Many thanks in advance!
>
>
> _______________________________________________
> Tkinter-discuss mailing list
> Tkinter-discuss <at> python.org
> http://mail.python.org/mailman/listinfo/tkinter-discuss

--

-- 
Kevin Walzer
Code by Kevin
http://www.codebykevin.com
Michael Lange | 2 Dec 2011 19:24
Picon

Re: Syntactic problems

Hi,

Thus spoketh Kevin Walzer <kw <at> codebykevin.com> 
unto us on Fri, 02 Dec 2011 10:45:04 -0500:

> > Â Â Â  .t tag configure f[incr count] -font [list $family 10]
> > Â
> > The function *list* of *Tcl* seems to be mainly dedicated to solve
> > this odd problem with the dereferencing of multiword contents of
> > variables (*family* in this case, which holds the name of the font).
> > But apparently this does not work when *Tcl/Tk* are finally moved by
> > *Tkinter* during the execution of the script or at least I have been
> > unable to find a way to make it work in due form.
> 
> I'm not quite clear on what problem you are experiencing here, as there 
> are no code snippets or Python errors outlined.
> 
> Are you just trying to understand the underlying Tcl idioms?

Maybe Francisco meant the following:

>>> l = Label(text='foo')
>>> l.pack()
>>> l.config(font='Helvetica 12')

this works, but:

>>> l.config(font='Bitstream Vera Sans 12')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1205, in configure
    return self._configure('configure', cnf, kw)
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1196, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: expected integer but got "Vera"

I think the Tkinter equivalent to tcl's list command in this context is
to simply pass a sequence instead of a string to the font option:

>>> l.config(font=('Bitstream Vera Sans', '12'))
>>> 

just like one would do in other cases where Tk expects a list, as e.g.
canvas coords.

Best regards

Michael

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

It would seem that evil retreats when forcibly confronted.
		-- Yarnek of Excalbia, "The Savage Curtain", stardate
5906.5
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Francisco Gracia | 3 Dec 2011 18:48
Picon

Syntactic problems

Many thanks to you both, Kevin and Michael for your quick and sensible responses. My problems are more in the line suggested by Michael, although his hint has not solved them, at least as I have tried to implement it.

In order for you to have all the information together, I transcribe the original Tcl code and my *porting* of it to *tkinter*. I commented it for my own use, in the process of conjecturing and confirming what the original code was intended to perform.

If you run the original code with *tclsh* or *wish* and then my code with *Idle*, you will see very clearly where the problem lies.

Kind regards

Francisco

# original Tcl code
# offered as example in the *font manual page* of TkDocs.
# Runs without problems with *tclsh* and *wish*

# pack [text .t -wrap none] -fill both -expand 1
# set count 0
# set tabwidth 0
# foreach family [lsort -dictionary [font families]] {
#    .t tag configure f[incr count] -font [list $family 10]
#    .t insert end ${family}:\t {} \
#            "This is a simple sampler\n" f$count
#    set w [font measure [.t cget -font] ${family}:]
#    if {$w+5 > $tabwidth} {
#        set tabwidth [expr {$w+5}]
#        .t configure -tabs $tabwidth
#    }
# }


from tkinter import *
from tkinter import font


# creation of the main window
master = Tk()

# creation of a text widget
tw = Text( master )
tw.config( wrap = NONE )
tw.pack( fill = BOTH, expand = 1 )

tw.insert( END, "Display of available fonts:\n\n" )

count = 0
tabwidth = 0

# identification of the font being used
f1 = tw.cget( 'font' )

# a measurement function used later
# is a method of class *tkinter.font.Font*,
# so that it is good to have the required instance of it
fo = font.Font( font = ( f1, 10 ) )

# let us get the ordered list of all
# available font families
sampler = sorted( list( font.families() ) )

# handling and display of the elements
for f in sampler :
    # the counter is updated
    count += 1
    # display of the provided font name plus
    # a separator and a tabulator
    tw.insert( END, f + ":\t" )
    # creation of an individual name for the tag
    # that will be applied to the sample for this item
    ftag = f + str( count )

    # my (vain) efforts to solve the multiword problem
    if ' ' in f :
#        fm = "('" + f + "', '10')"   # as for Michael's hint
        fm = '[list ' + f + ']'
#        fm = f.replace( ' ', '_' )
#        fm = f.replace( ' ', '' )
        tw.tag_config( ftag, font = ( fm, 10 ) )
#        tw.tag_config( ftag, font = fm )
    else :
        # single word names work as expected
        tw.tag_config( ftag, font = ( f, 10 ) )
    # and the sample text:
    tw.insert( END, "This is a simple sampler\n", ftag )
   
    # nice columnar disposition by
    # a clever configuration of the tabulator
    w = fo.measure( f + ':' )
    if ( w + 5 ) > tabwidth :
        tabwidth = w + 5
        # this equalizes all the lines as required
        tw.config( tabs = tabwidth )

if __name__ == '__main__' :
    master.mainloop()



_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Michael Lange | 3 Dec 2011 19:16
Picon

Re: Syntactic problems

Hi Francisco,

Thus spoketh Francisco Gracia <fgragu023 <at> gmail.com> 
unto us on Sat, 3 Dec 2011 18:48:36 +0100:

> Many thanks to you both, Kevin and Michael for your quick and sensible
> responses. My problems are more in the line suggested by Michael,
> although his hint has not solved them, at least as I have tried to
> implement it.

The problem in you code is not the white space in the font name but the
white space in the tag name (actually this is where the python code
differs from the tcl example, maybe due to a typo).
I changed (the relevant part of) your code into:

for f in sampler :
    # the counter is updated
    count += 1
    # display of the provided font name plus
    # a separator and a tabulator
    tw.insert( END, f + ":\t" )
    # creation of an individual name for the tag
    # that will be applied to the sample for this item

    ftag =  'f' + str( count )# please note the quotes !

    tw.tag_config( ftag, font = ( f, 10 ) )
    # and the sample text:
    tw.insert( END, "This is a simple sampler\n", ftag )

and then it worked as expected.

Best regards

Michael

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

First study the enemy.  Seek weakness.
		-- Romulan Commander, "Balance of Terror", stardate 1709.2
Francisco Gracia | 4 Dec 2011 13:36
Picon

Re: Syntactic problems



2011/12/3 Michael Lange <klappnase <at> web.de> said:

Hi Francisco,
 
The problem in you code is not the white space in the font name but the
white space in the tag name ...

You are right, Michael, that was a mistake on my side. It was not a typo, but a
confusion due to my bad knowledge of *Tcl*'s syntax and to my not
having given due consideration to the bussines at hand. Changing the name of the tag to an only word eliminates the problem in this case and the tag's handling becomes unproblematic.

... and then it worked as expected.

But with this not all problems are solved. Although the display
varies with the machine used, if one scans carefully
the whole output, one usually finds one or more lines where long font
names of several words invade the area of the samples display; this should not happen and does not happen with Tcl's script. This is due to the
malfunction of the measuring function and in this case one cannot
avoid that the string to be measured has several words; on the contrary this should be the normal case.

It seems however that I have been lucky enough to find an apparently general solution. You can see it in the transcription of the whole script that follows; for the moment this seems to be my final version.

I even consider the patch general because it also solves the difficulty of your initial sample code, so that while

>>> c = 'Bitstream Vera Sans 12'
>>> l.config(font=c)

continues originating an error,

>>> c = '"[list Bitstream Vera Sans 12]"'
>>> l.config(font=c)

seems to work.

I want to thank you very much for your kindness and your interest.

Best regards

Francisco

# *Sampler.py*
# Display the names of the typographical fonts
# available in the present machine
# with a sample of the appearance of each one.

# Python version of the following *Tcl* code
# offered as example in the *font* manual page of *TkDocs*:

# pack [text .t -wrap none] -fill both -expand 1
# set count 0
# set tabwidth 0
# foreach family [lsort -dictionary [font families]] {
#    .t tag configure f[incr count] -font [list $family 10]
#    .t insert end ${family}:\t {} \
#            "This is a simple sampler\n" f$count
#    set w [font measure [.t cget -font] ${family}:]
#    if {$w+5 > $tabwidth} {
#        set tabwidth [expr {$w+5}]
#        .t configure -tabs $tabwidth
#    }
# }


from tkinter import *
from tkinter import font

# creation of the main window
master = Tk()

# creation of a text widget
tw = Text( master )
tw.config( wrap = NONE )
tw.pack( fill = BOTH, expand = 1 )

tw.insert( END, "Display of available fonts:\n\n" )

count = 0           # cardinal of the element
tabwidth = 0        # tabulator's position (in pixel)

# identification of the font in use (default)
f1 = tw.cget( 'font' )

# a measurement function to be applied later
# is a method of class *tkinter.font.Font*, so that
# it is good to get now the required instance of it
fo = font.Font( font = ( f1, 10 ) )

# let us get the alphabetically ordered list
# of all the font families available in this machine
sampler = sorted( list( font.families() ) )

# handling and display of its elements
for f in sampler :
    # the counter is updated
    count += 1
    # the provided font name is displayed
    # plus a separator and a tabulator
    tw.insert( END, f + ":\t" )
    # creation of an individual name for the tag
    # to be applied to this item's sample
    ftag = 'f' + str( count )
    # creation and typographical configuration of *ftag*
    tw.tag_config( ftag, font = ( f, 10 ) )
    # the sample text is finally tagged and displayed
    tw.insert( END, "This is a simple sampler\n", ftag )
   
    # nice columnar disposition of the output by
    # a clean and clever (re)configuration of the tabulator
   
    f = f + ':'
    if ' ' in f :       # the name has several words
        # (these strings of several words
        # are not well handled here by the complex *Tkinter/Tcl/Tk*;
        # fortunately it seems that the problem can be solved
        # by mimicking *Tcl*'s syntax for the occasion,
        # i.e. by flanking them with
        # the *magic* prefix:     '"[list '
        # and the *magic* suffix: ']"'      )
        f = '"[list ' + f + ']"'       

    w = fo.measure( f )         # in pixel as unit
    if ( w + 5 ) > tabwidth :
        tabwidth = w + 5
        # this aligns all the lines as required
        tw.config( tabs = tabwidth )

if __name__ == '__main__' :
    master.mainloop()



_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Bryan Oakley | 6 Dec 2011 18:09
Picon
Gravatar

why tkinter hangs on windows with tcl server socket?

I’m running the following program on Windows, and when I close the app
by clicking on the window manage close button the app hangs. Obviously
this isn’t my real code, but I can’t explain why the code is hanging,
or what the workaround is to get it to not hang.  Interestingly, the
last line of code is executing, so the main loop is terminating but
the python process refuses to die – I’m having to kill it via the task
manager. Even explicitly calling sys.exit() has no effect.

Notice how I create a server socket, then immediately close the
socket. No client is connecting to the server.  It doesn’t matter that
I close it or not, or if I close it after some period of time, it is
the creation of the socket that seems to cause tkinter to hang.

Any ideas?

This is with python 2.7.2.5 from ActiveState, FWIW.

# --- the code ---
import Tkinter as tk

root = tk.Tk()
root.eval('''
    proc Server {args} {puts "Server... $args"}
    set ::the_socket [socket -server Server 0]
    close $::the_socket
''')
root.mainloop()
print "mainloop has exited"
# --- end of the code ---
Lynn Oliver | 7 Dec 2011 19:07
Picon

Differences between two installations

I've been using Python 2.7.2 with Tkinter.Tcl version 8.5.11, which I installed using the instructions here.  Recently I did another installation using the instructions here in order to get SciPy to build correctly. The newer installation also shows as Python 2.7.2 and Tkinter.Tcl 8.5.11, but the same code does not work on both installs. I am on a Mac running OS X 10.7.2.

On the earlier install, LabelFrame() keywords "bd" and "font" are recognized, while on the second install they are not. I can use "borderwidth" instead of "bd" on the second install.

Also on the earlier install, LabelFrame(text="mylabel") displays the text imbedded in the frame. On the second install, the text is displayed outside of the frame. From the description here under the heading "Label Frames", I see that is the expected behavior, but it is different on the earlier install.

The biggest problem is not being able to use named fonts on the second install, but the differences in how LabelFrame works also causes some platform-specific issues.

On both builds, Tkinter.__version__ returns $Revision$.

Any ideas as to what is going on?

-Lynn


_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
Martin B | 18 Dec 2011 16:48

Getting object Y pos in Canvas

Hi all,
For my little app i need know last Y coord of object i created on
Canvas.
I'm creating a text Object. For his last X coord i use
font.measure('bla bla bla') this working.But i want know last Y coord
coz i need create next text object bottom.

How i get Y if i create this text object
create_text(0, 0, anchor='nw', text='bla\n bla\n bla', font=boldfont)

thanks
Martin B | 18 Dec 2011 17:32

Re: Getting object Y pos in Canvas

V Sun, 18 Dec 2011 16:48:40 +0100
Martin B <spooky.ln <at> tbs-software.com> napsáno:

sry i forgot add tag to object.
now i get bounding box of objects with canvas.bbox('mytag')

sry once more.

> Hi all,
> For my little app i need know last Y coord of object i created on
> Canvas.
> I'm creating a text Object. For his last X coord i use
> font.measure('bla bla bla') this working.But i want know last Y coord
> coz i need create next text object bottom.
> 
> How i get Y if i create this text object
> create_text(0, 0, anchor='nw', text='bla\n bla\n bla', font=boldfont)
> 
> thanks
> _______________________________________________
> Tkinter-discuss mailing list
> Tkinter-discuss <at> python.org
> http://mail.python.org/mailman/listinfo/tkinter-discuss

_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss <at> python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss

Gmane