Reputation: 1134
I'm currently having a little bit of an issue - I have a class called tableView, and what I'd really like is for it to be used like a normal widgit inside a TK() frame. I want to be able to call it by doing something like this -
root = Tk()
root.wm_title("Main")
ttk.Button(root, text="Add new student").grid(row = 0, column = 0)
ttk.Button(root, text="Edit Student").grid(row = 0, column = 1)
ttk.Button(root, text="Edit Student").grid(row = 0, column = 2)
columns = ['ID', 'First Name', 'Last Name', 'Registration No']
rows = server.select("Student")
TableView(root, columns, rows)
root.mainloop()
And for it to distplay in my current tk() frame. Currently it pops up in a window of its own, and I was interested in finding out how I can add just add it to the current frame. I assume it must inherit from a widget, and use a parent value, somehow? How tricky is it to accomplish this? Is there an easily extendible class?
class TableView(object):
"""use a ttk.TreeView as a multicolumn ListBox"""
def __init__(self, columns, rows):
self.rows = rows
self.columns = columns
self.tree = None
self._setup_widgets()
self._build_tree()
def _setup_widgets(self):
container = ttk.Frame()
container.pack(fill='both', expand=True)
self.tree = ttk.Treeview(columns=self.columns, show="headings")
self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
def _build_tree(self):
for col in self.columns:
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 self.rows:
self.tree.insert('', 'end', values=item)
def sortby(tree, col, descending):
"""sort tree contents when a column header is clicked on"""
data = [(tree.set(child, col), child)
for child in tree.get_children('')]
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)))
root = tk.Tk()
root.wm_title("Journeys")
c = tk.Canvas(root, height=-8, width=800)
c.pack()
I'm relatively new to python, so any help is appreciated - also, is this a reasonable way of making a table - are there any better ways/libs already out there?
Thanks for your help Ollie
Upvotes: 0
Views: 266
Reputation: 386275
Your TableView
class needs to inherit from Frame
. When you do that, you can treat it just like any other widget.
For example:
class TableView(Frame):
def __init__(self, parent, columns, rows):
Frame.__init__(self, parent)
self.columns = columns
self.rows = rows
...
self._setup_widgets()
...
def setup_widgets(self):
self.tree = ttk.Treeview(self, columns=self.columns, show="heading")
self.tree.grid(column=0, row=0, sticky="nsew")
...
You don't need to create a container, because the object is its own container. Any child widgets within the class should be packed/gridded to self
so that they are inside the container.
Also, you shouldn't call tk.Tk() anywhere except in your main program -- that is why you get a separate window.
Your main program goes virtually unchanged, except you need to add a line of code to place the widget in the grid:
root = Tk()
root.wm_title("Main")
ttk.Button(root, text="Add new student").grid(row = 0, column = 0)
ttk.Button(root, text="Edit Student").grid(row = 0, column = 1)
ttk.Button(root, text="Edit Student").grid(row = 0, column = 2)
columns = ['ID', 'First Name', 'Last Name', 'Registration No']
rows = server.select("Student")
# create an instance of the TableView widget
tableview = TableView(root, columns, rows)
# ... and add it to the root window
tableview.grid(row=1, column=0, columnspan=3)
root.mainloop()
Upvotes: 1