Search code examples
pythonstringtkinterstring.format

TkInter ListBox and use of .format


I am using this command:

self.licenseBox.insert(END, "{:30}{:90}{:20}{:5}".format(item[0],
                                                    item[1], item[2], item[3]))

But .format will add the item then the column width. For example if item[0] = "foo", the first column is 33 wide and means the following parameters are off by three.

Any work around ?


Solution

  • But .format will add the item then the column width.

    format() does no such thing:

    print "1234567890" * 2
    print "{:4}{:4}{:4}{:4}".format('aaaa', 'bbbb', 'cccc', 'dddd')
    
    --output:--
    12345678901234567890
    aaaabbbbccccdddd
    

    The total width of the output is 16 = 4 x 4.

    You should explicitly specify the alignment:

    lb.insert(tk.END, "{:<5}-{:<2}".format(123, 9))
    

    The docs say:

    '<'   Forces the field to be left-aligned within the available space 
          (this is the default for most objects).
    

    That 'most objects' language is what I think you may be running afoul of. Strings, numbers, etc. have a __format__() method that is called when they are asked to display themselves when you call the format() method on them. Check this out:

    print "{:4}".format("a")
    print "{:4}".format(9)
    
    --output:--
    a   
       9
    

    Strings and numbers have different defaults for their justification. So I would not rely on the defaults--be explicit instead, and then you will know how the output will be justified.

    Having said that, I have to use 17 for the min field width to actually get 10:

    import Tkinter as tk
    
    root = tk.Tk()
    root.geometry("1000x200")
    
    lb = tk.Listbox(root, width=150)
    lb.insert("1", "{:4}{:4}".format("a", "b") )
    lb.insert(tk.END, "1234567890" * 4)
    lb.insert(tk.END, "{:<17}{:<10}".format(100, 200) )
    lb.pack()
    
    root.mainloop()
    

    With that code, I see 200 starting in column 11. Okay, that alignment problem has to do with tkinter using a default font that is not fixed width, i.e. all characters do not occupy the same amount of space. If you are trying to align columns, you need to use a fixed width font. Try something like this:

    import Tkinter as tk
    import tkFont
    
    root = tk.Tk()
    
    my_font = tkFont.Font(family="Monaco", size=12)  #Must come after the previous line.
    
    root.geometry("1000x200")
    
    lb = tk.Listbox(root, width=150, font=my_font)
    lb.insert("1", "{:4}{:4}".format("a", "b") )
    lb.insert(tk.END, "1234567890" * 4)
    lb.insert(tk.END, "{:>10}{:>10}".format(100, 200) )
    lb.pack()
    
    root.mainloop()