How to set width of Treeview in tkinter of python

23,666

After searching for over a week now, I stumbled upon a very easy way to do the 'magic'.

  1. I read the current size of my mainWindow
  2. Add the data to the treeView
  3. Set the width of each column depending on the max length of an entry (by using measure)
  4. Calling the update function on my mainWindow (not sure if this is needed)
  5. Setting the size of the mainWindow to the stored values

And here is my code:

def reloadTreeViewData(self):
    # get current size of main window
    curMainWindowHeight = self.parent.winfo_height()
    curMainWindowWidth = self.parent.winfo_width()

    #delete all
    for child in self.tree.get_children():
        self.dicData = {}
        self.tree.delete(child)

    # reload all
    count = 0
    for row in self.data:
        adding_string = []
        for element in self.indexlist:
            adding_string.append(str(row[element]))
        insert_ID = self.tree.insert('', 'end', text=count, values=adding_string)
        # save the data in it's original types in a dictionary
        self.dicData[insert_ID] = [row[x] for x in self.indexlist]
        count += 1

    # reset column width
    max_colum_widths = [0] * len(self.indexlist)
    for child in self.tree.get_children():
        rowData = self.dicData[child]
        for idx, rowIdx in enumerate(self.indexlist):
            item = rowData[idx]
            new_length = self.myFont.measure(str(item))
            if new_length > max_colum_widths[idx]:
                max_colum_widths[idx] = new_length
    for idx, item in enumerate(self.attributeList):
        if int(max_colum_widths[idx]) < 50:
            self.tree.column(item, width=50)
        else:
            self.tree.column(item, width=int(max_colum_widths[idx]))

    # restore the size of the mainWindow
    self.parent.update()
    self.parent.geometry("" + str(curMainWindowWidth) + "x" + str(curMainWindowHeight))

My headings for the treeView are stored in self.attributeList but the data comes from a database, which has way more columns I want to show. So I use a mapping list which is stored as self.indexlist.

self.myFont is defined as follows:

    import tkinter.font as tkFont
    self.myFont = tkFont.Font(self, "Calibri", 12)

I use the treeview just to show the data and a seperate dictionary to save the data, by using the child-id (returned by insert) as key. This way I keep the real data I inserted into the treeView. This is important for strings like '0005' which will return as 5 (integer) when you recall it from the treeview and you lose the leading zeros.

I hope this solution helps others. If there is a more convenient solution feel free to comment.

If you have any questions about my code, feel free to ask.

Share:
23,666
ddming000
Author by

ddming000

Updated on July 05, 2022

Comments

  • ddming000
    ddming000 almost 2 years

    Recently, I use tkinter TreeView to show many columns in Python. Specifically, 49 columns data in a treeview. I use grid to manage my widgets.

    I found out the width of the treeview only depends on the width of columns.

    My question is, How can I set the width of the Treeview. (The default width is the summation of all columns' width)

    When all my column width is set as 20. This is 49 columns. :) enter image description here

    Here is my main code :

    frame = Frame(self.master, width = 1845, height = 670)
    frame.place(x = 20, y = 310)
    tree_view = Treeview(frame, height = 33, selectmode = "extended")
    for i in range(len(id_list)):
        tree_view.column(id_list[i], width = width_list[i], anchor = CENTER)
        tree_view.heading(id_list[i] , text = text_list[i])
    tree_view["show"] = "headings"
    # Omit the declaration of scrollbar    
    tree_view['yscroll'] = self.y_scollbar.set
    tree_view['xscroll'] = self.x_scollbar.set
    tree_view.grid(row = 0, column = 0, sticky = NSEW)
    for item in detail_info_list:
        tree_view.insert("",0, text = str(item.id), value=(...))
    

    id_list,width_list,text_list is used to store columns information. detail_info_list is to store the data showed in the Treeview.

    My target is when I define a large width(for example: 3000) of some column, my treeview could show the data as I expected. But the treeview is across my screen and the horizontal scrollbar also can't slide.

    When 17th column is set as 1500: enter image description here

    I can't see my buttons, and I can't slide the horizontal scrollbar.

    Also, I have tried some solution.

    • Define a frame to be the Treeview parent. And define the width and height to constraint the Treeview. But it didn't work.
    • I looked up some documents and search for this question. I don't find any solution to set the width as a constant number.
  • jdehesa
    jdehesa almost 7 years
    Could you please explain this with a bit more of detail? I have seen that the initial column size defines the widget size of the tree... but how do you resize the columns after? Did you mean you resize them by hand, or by code, somehow after the widgets have already been laid out?
  • jdehesa
    jdehesa almost 7 years
    Nevermind, just figured it out! You can just call update() on the root Tk object first (which will do all the layout) and then resize the columns as you wish (in my case I use the measure method of tkinter.font.Font).
  • Aleksandar Beat
    Aleksandar Beat almost 6 years
    @jdehesa Can you please post the code how you did it, i cant figure it out?
  • jdehesa
    jdehesa almost 6 years
    @AleksandarBeat I have sth like this view = ttk.Treeview(frame, columns=cols, show="headings"), so first I do for col in cols: view.column(col, width=0) to have the "minimal width" tree, after that I run root.update() (root is the root Tk object), forcing a layout of the tree and fixing its width in the window, and then I set the heading and actual width with for col in cols: view.heading(col, text=col); view.column(col, width=col_width), where col_width is the desired column width (in my case font.measure(col), font being defined as tk.font.Font(root)).