Reputation: 285
Dear All I have been trying to insert a treeview in a child window using Tkinter but it has been quite complicated since I don't know how to put them together. Thank you very much in advance! Héctor
This is what I have done so far:
import Tkinter
from Tkinter import *
import tkFont
import ttk
root= Tk()
class McListBox(object):
def __init__(self):
self.tree = None
self._setup_widgets()
self._build_tree()
def _setup_widgets(self):
s = """
"""
msg = ttk.Label(wraplength="4i", justify="right", anchor="n",
padding=(6, 6, 6, 6, 6 ,6), text=s)
msg.pack(fill='x')
container = ttk.Frame()
container.pack(fill='both', expand=True)
self.tree = ttk.Treeview(columns=element_header, show="headings")
vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview)
hsb = ttk.Scrollbar(orient="horizontal", command=self.tree.xview)
self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)
self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
vsb.grid(column=1, row=0, sticky='ns', in_=container)
hsb.grid(column=0, row=1, sticky='ew', in_=container)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
def _build_tree(self):
for col in element_header:
self.tree.heading(col, text=col.title(),
command=lambda c=col: sortby(self.tree, c, 0))
self.tree.column(col, width=tkFont.Font().measure(col.title()))
for item in element_list:
self.tree.insert('', 'end', values=item)
for ix, val in enumerate(item):
col_w = tkFont.Font().measure(val)
if self.tree.column(element_header[ix], width=None) < col_w:
self.tree.column(element_header[ix], width=col_w)
def isnumeric(s):
for c in s:
if c in "0000123456789000-.":
numeric = True
else:
return False
return numeric
def change_numeric(data):
new_data = []
if isnumeric(data[0][0]):
for child, col in data:
new_data.append((float(child), col))
return new_data
return data
def sortby(tree, col, descending):
data = [(tree.set(child, col), child) for child in tree.get_children('')]
data = change_numeric(data)
data.sort(reverse=descending)
for ix, item in enumerate(data):
tree.move(item[1], '', ix)
tree.heading(col,
command=lambda col=col: sortby(tree, col, int(not descending)))
element_header = ["Device", "Type", "LETs Threshold (L0)"]
element_list = [('93L422', 'Bipolar', '0.6')]
mc_listbox = McListBox()
def Child_Window():
win2 = Toplevel()
message = "This is the child window"
Label(win2, text=message).pack()
Button(win2, text='OK', command=win2.destroy).pack()
Button(root, text='Bring up Message', command=Child_Window).pack()
root.mainloop()
Upvotes: 1
Views: 4766
Reputation: 385820
The solution is simple: every widget takes another widget as its first parameter, and this parameter defines the parent of the new widget. The new widget by default will appear in the patent widget when you use pack
, grid
or place
. That's really all you need to know.
So, if you want self.tree
to be in win2
, win2
must* be given to the treeview constructor as the first argument.
Note that you cannot create a widget in one window and then move it to another (where "window" is defined as "an instance of Tk
or Toplevel
"). A window and its parent must share the same top-most widget as an ancestor.
* "Must" is a bit too strong, because you can have widgets appear inside widgets other than their immediate parent. I don't think that is relevant to what you are trying to do here, so I won't elaborate to avoid confusion.
Upvotes: 1
Reputation: 649
Treeview should be constructed with parent window as a first argument. I changed Child_Window method so that it displays very simple tree. You can now easily adapt your tree to my example. I would also suggest refactoring code in a way that all methods are contained in McListBox class. I used pack geometry manager instead of grid manager. Here is my example:
def Child_Window():
win2 = Toplevel()
message = "This is the child window"
Label(win2, text=message).pack()
element_header=['1st','2nd','3rd']
treeScroll = ttk.Scrollbar(win2)
treeScroll.pack(side=RIGHT, fill=Y)
tree = ttk.Treeview(win2,columns=element_header, show="headings", yscrollcommand = treeScroll)
tree.heading("1st", text="1st")
tree.pack(side=LEFT, fill=BOTH)
treeScroll.config(command=tree.yview)
After discussion with Hector I decided to paste all modified class which should work like required. By the way I refactored it so that all functions and variables are members of a class. Works fine with Python 2.7.5.
import Tkinter
from Tkinter import *
import tkFont
import ttk
class ModifiedMcListBox(object):
def __init__(self):
self.root= Tk()
self.tree = None
self.element_header = ["Device", "Type", "LETs Threshold (L0)"]
self.element_list = [('93L422', 'Bipolar', '0.6')]
self._setup_widgets()
self._build_tree()
self.root.mainloop()
def _setup_widgets(self):
s = """
"""
msg = ttk.Label(wraplength="4i", justify="right", anchor="n",
padding=(6, 6, 6, 6, 6 ,6), text=s)
msg.pack(fill='x')
container = ttk.Frame()
container.pack(fill='both', expand=True)
self.tree = ttk.Treeview(columns=self.element_header, show="headings")
vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview)
hsb = ttk.Scrollbar(orient="horizontal", command=self.tree.xview)
self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)
self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
vsb.grid(column=1, row=0, sticky='ns', in_=container)
hsb.grid(column=0, row=1, sticky='ew', in_=container)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
Button(self.root, text='Bring up Message', command=self.Child_Window).pack()
def _build_tree(self):
for col in self.element_header:
self.tree.heading(col, text=col.title(),
command=lambda c=col: self.sortby(self.tree, c, 0))
self.tree.column(col, width=tkFont.Font().measure(col.title()))
for item in self.element_list:
self.tree.insert('', 'end', values=item)
for ix, val in enumerate(item):
col_w = tkFont.Font().measure(val)
if self.tree.column(self.element_header[ix], width=None) < col_w:
self.tree.column(self.element_header[ix], width=col_w)
def isnumeric(self,s):
for c in s:
if c in "0000123456789000-.":
numeric = True
else:
return False
return numeric
def change_numeric(self,data):
new_data = []
if self.isnumeric(data[0][0]):
for child, col in data:
new_data.append((float(child), col))
return new_data
return data
def sortby(self,tree, col, descending):
data = [(tree.set(child, col), child) for child in tree.get_children('')]
data = self.change_numeric(data)
data.sort(reverse=descending)
for ix, item in enumerate(data):
tree.move(item[1], '', ix)
tree.heading(col,
command=lambda col=col: sortby(tree, col, int(not descending)))
def Child_Window(self):
win2 = Toplevel()
message = "This is the child window"
Label(win2, text=message).pack()
new_element_header=['1st','2nd','3rd']
treeScroll = ttk.Scrollbar(win2)
treeScroll.pack(side=RIGHT, fill=Y)
tree = ttk.Treeview(win2,columns=new_element_header, show="headings", yscrollcommand = treeScroll)
tree.heading("1st", text="1st")
tree.heading("2nd", text="2nd")
tree.heading("3rd", text="3rd")
tree.pack(side=LEFT, fill=BOTH)
treeScroll.config(command=tree.yview)
mc_listbox = ModifiedMcListBox()
Upvotes: 2