質問

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

役に立ちましたか?

解決

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()
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top