How to set width of Treeview in tkinter of python

2019-07-25 07:57发布

问题:

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. :)

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:

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.

回答1:

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.



回答2:

After trying so many ways to solve this problem, I find out a simple but silly solution. After initializing the width of the Treeview, you just need to resize the with of the column and the width of the Treeview will NOT change.

Perhaps, this is the constraint of Tcl/Tk.