使用 Tkinter 显示带有列的列表框?

Posted

技术标签:

【中文标题】使用 Tkinter 显示带有列的列表框?【英文标题】:Display Listbox with columns using Tkinter? 【发布时间】:2011-07-14 06:04:42 【问题描述】:

我正在尝试在具有列的 Tkinter 中创建一个 Listbox

我从数据库查询记录返回,并希望在每条记录的自己的列中显示每个条目。

看着Listbox,感觉那里应该有这个功能但是找不到。我应该使用什么小部件来执行此操作?我一直在网上搜索,但文档非常稀少。

【问题讨论】:

基本的 Tk ListBox 不是多列的。因此,您需要找到各种多列列表框之一,例如 TkTreectrl、ttk::treeview 或许多其他列表框之一。 TkTreeCtrl 是其中最强大和最通用的。 【参考方案1】:

使用TkTreectrl:

import Tkinter as tk
import TkTreectrl as treectrl
import sqlite3

def setup_table(connection):
    cursor=connection.cursor()
    cursor.execute('''CREATE TABLE foo
                      (id INTEGER PRIMARY KEY AUTOINCREMENT,
                      bar TEXT)''')
    sql='INSERT INTO foo (bar) values (?)'
    for i in range(10):
        cursor.execute(sql,(i,))
    cursor.execute(sql,(u'\NINFINITY',))

def select_cmd(selected):
    print 'Selected items:', selected

def main():
    connection=sqlite3.connect(':memory:')   
    setup_table(connection)
    cursor=connection.cursor()

    root = tk.Tk()
    root.title('Simple MultiListbox demo')
    mlb = treectrl.MultiListbox(root)
    mlb.pack(side='top', fill='both', expand=1)
    tk.Button(root, text='Close', command=root.quit).pack(side='top', pady=5)
    mlb.focus_set()   
    mlb.configure(selectcmd=select_cmd, selectmode='extended')
    mlb.config(columns=('Column 1', 'Column 2'))
    cursor.execute('SELECT * from foo')
    for row in cursor.fetchall():
        mlb.insert('end',*map(unicode,row))
    root.mainloop()

if __name__=='__main__':
    main()

产量

【讨论】:

如何在 Windows 10 中安装 TkTreectrl? 安装有说明在有点莫名其妙的主页tkintertreectrl.sourceforge.net【参考方案2】:

一个简单的解决方案是并排使用两个列表框。没有真正的魔法,你只需要做一些额外的工作来让一个滚动条来控制两者(很容易做到)并让两个同​​步中的选择同步(也很容易做到)。

【讨论】:

这种能力的一些例子将是一个很好的补充【参考方案3】:

您可以使用 Ttk/Tkinker Treeview 小部件,它用于处理表格数据。

以下是一个类的example,它使用Treeview 小部件来显示字符串的多列列表:

'''
Here the TreeView widget is configured as a multi-column listbox
with adjustable column width and column-header-click sorting.
'''
try:
    import Tkinter as tk
    import tkFont
    import ttk
except ImportError:  # Python 3
    import tkinter as tk
    import tkinter.font as tkFont
    import tkinter.ttk as ttk

class MultiColumnListbox(object):
    """use a ttk.TreeView as a multicolumn ListBox"""

    def __init__(self):
        self.tree = None
        self._setup_widgets()
        self._build_tree()

    def _setup_widgets(self):
        s = """\click on header to sort by that column
to change width of column drag boundary
        """
        msg = ttk.Label(wraplength="4i", justify="left", anchor="n",
            padding=(10, 2, 10, 6), text=s)
        msg.pack(fill='x')
        container = ttk.Frame()
        container.pack(fill='both', expand=True)
        # create a treeview with dual scrollbars
        self.tree = ttk.Treeview(columns=car_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 car_header:
            self.tree.heading(col, text=col.title(),
                command=lambda c=col: sortby(self.tree, c, 0))
            # adjust the column's width to the header string
            self.tree.column(col,
                width=tkFont.Font().measure(col.title()))

        for item in car_list:
            self.tree.insert('', 'end', values=item)
            # adjust column's width if necessary to fit each value
            for ix, val in enumerate(item):
                col_w = tkFont.Font().measure(val)
                if self.tree.column(car_header[ix],width=None)<col_w:
                    self.tree.column(car_header[ix], width=col_w)

def sortby(tree, col, descending):
    """sort tree contents when a column header is clicked on"""
    # grab values to sort
    data = [(tree.set(child, col), child) \
        for child in tree.get_children('')]
    # if the data to be sorted is numeric change to float
    #data =  change_numeric(data)
    # now sort the data in place
    data.sort(reverse=descending)
    for ix, item in enumerate(data):
        tree.move(item[1], '', ix)
    # switch the heading so it will sort in the opposite direction
    tree.heading(col, command=lambda col=col: sortby(tree, col, \
        int(not descending)))

# the test data ...

car_header = ['car', 'repair']
car_list = [
('Hyundai', 'brakes') ,
('Honda', 'light') ,
('Lexus', 'battery') ,
('Benz', 'wiper') ,
('Ford', 'tire') ,
('Chevy', 'air') ,
('Chrysler', 'piston') ,
('Toyota', 'brake pedal') ,
('BMW', 'seat')
]


if __name__ == '__main__':
    root = tk.Tk()
    root.title("Multicolumn Treeview/Listbox")
    listbox = MultiColumnListbox()
    root.mainloop()

这些是使用Treeview 小部件的结果的一些图片:

【讨论】:

我尝试尽可能多地改进tkinter/ttk 上的问题和答案,以便为其他人提供有关这些工具包的良好参考。我认为 tkinter 应该得到更好的支持,主要是在论坛方面。 tkinter/ttk 上没有真正的网络专用论坛。 是否可以更新此视图?例如,新记录被插入到数据库表中? @NafisAhmad 是的,有可能。只需添加一个按钮,它将更改数组 vales car_list。据我记得,当您更改数据时,表格会自动更新。抱歉,我无法运行我自己的代码,所以我无法给你一个运行示例。

以上是关于使用 Tkinter 显示带有列的列表框?的主要内容,如果未能解决你的问题,请参考以下文章

使用箭头键滚动的 Tkinter 列表框

我可以双击 tkinter 列表框选项来调用 Python 中的函数吗?

如何在 Tkinter 列表框中插入时添加自动滚动?

tkinter窗口系列之一——列表框

列表框在tkinter中显示数据库中的表

在python中保存带有列表列的数据框