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.
After searching for over a week now, I stumbled upon a very easy way to do the 'magic'.
- I read the current size of my mainWindow
- Add the data to the treeView
- Set the width of each column depending on the max length of an entry (by using
measure
)
- Calling the
update
function on my mainWindow (not sure if this is needed)
- 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.
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.