【问题标题】:How to add checkbuttons to every row of a table read from csv in tkinter?如何在 tkinter 中从 csv 读取的表格的每一行添加复选按钮?
【发布时间】:2019-12-17 09:43:54
【问题描述】:

我有一个从 csv 读取并使用 tkinter 显示的 4 列的表。我想在名为“已服务”的列中每一行的末尾添加一个复选按钮。然而,我没有得到一个检查按钮,而是得到'.!framed.!checkbut'。

这是我的代码:

from tkinter import *
from tkinter import ttk
from ttkthemes import ThemedStyle
import tkinter.font as font
import csv

root = Tk()
root.title("A") #title shown in bar
root.iconbitmap(r'C:/Users/...') #icon shown in bar
TableMargin = ttk.Frame(root)
TableMargin.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.state('zoomed') #fullscreen

# Setting Theme
style = ThemedStyle(TableMargin)
style.set_theme("black")

#Heading
label = ttk.Label(TableMargin, text='Orders')
label['font'] = font.Font(size=20, weight="bold")
label.grid(row=0, sticky=(N),pady=5)

#Designing of Table
style = ttk.Style()
style.configure("Treeview.Heading", font=(None, 13))
# scrollbarx = Scrollbar(TableMargin, orient=HORIZONTAL)
# scrollbary = Scrollbar(TableMargin, orient=VERTICAL)
tree = ttk.Treeview(TableMargin, columns=("Table No.", "Order", "Time", "Served"), height=400, selectmode="extended") #, yscrollcommand=scrollbary.set, xscrollcommand=scrollbarx.set
# scrollbary.config(command=tree.yview)
# scrollbary.pack(side=RIGHT, fill=Y)
# scrollbarx.config(command=tree.xview)
# scrollbarx.pack(side=BOTTOM, fill=X)
tree.heading('Table No.', text="Table No.", anchor=W)
tree.heading('Order', text="Order", anchor=W)
tree.heading('Time', text="Time", anchor=W)
tree.heading('Served', text="Served", anchor=W)
tree.column('#0', stretch=NO, minwidth=0, width=0)
tree.column('#1', stretch=NO, minwidth=0, width=100)
tree.column('#2', stretch=NO, minwidth=0, width=600)
tree.column('#3', stretch=NO, minwidth=0, width=100)
tree.column('#4', stretch=NO, minwidth=0, width=100)

tree.grid(row=0, pady=50,padx=190,sticky=(N, E, S))

with open('C:/Users/...', encoding = "utf-8-sig") as f:
    reader = csv.DictReader(f, delimiter=',')
    for row in reader:
        table = row['Table']
        order = row['Order']
        time = row['Time']
        var = IntVar()
        served = ttk.Checkbutton(TableMargin, text="", variable=var)
        served.grid()
        tree.insert("", 1, values=(table, order, time, served))

【问题讨论】:

标签: python python-3.x tkinter


【解决方案1】:

您可以使用复选框的图像来做到这一点。首先,我使用 Row 布局将图像放在右侧:

style.layout('cb.Treeview.Row',
                     [('Treeitem.row', {'sticky': 'nswe'}),
                      ('Treeitem.image', {'side': 'right', 'sticky': 'e'})])

然后,我在每个树项上使用标签“已选中”和“未选中”来控制复选框的图像(请参见下面的代码)。

我还将项目的 id 作为标签添加到每个项目,以便我可以将此标签绑定到按钮点击。当有点击时,我通过identify_column(event.x) 检查点击是否在“已服务”列中,如果是,我使用标签切换复选框的状态。

这里是完整的代码:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()


class CbTreeview(ttk.Treeview):
    def __init__(self, master=None, **kw):
        kw.setdefault('style', 'cb.Treeview')
        kw.setdefault('show', 'headings')  # hide column #0
        ttk.Treeview.__init__(self, master, **kw)
        # create checheckbox images
        self._im_checked = tk.PhotoImage('checked',
                                         data=b'GIF89a\x0e\x00\x0e\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x0e\x00\x0e\x00\x00\x02#\x04\x82\xa9v\xc8\xef\xdc\x83k\x9ap\xe5\xc4\x99S\x96l^\x83qZ\xd7\x8d$\xa8\xae\x99\x15Zl#\xd3\xa9"\x15\x00;',
                                         master=self)
        self._im_unchecked = tk.PhotoImage('unchecked',
                                           data=b'GIF89a\x0e\x00\x0e\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x0e\x00\x0e\x00\x00\x02\x1e\x04\x82\xa9v\xc1\xdf"|i\xc2j\x19\xce\x06q\xed|\xd2\xe7\x89%yZ^J\x85\x8d\xb2\x00\x05\x00;',
                                           master=self)
        style = ttk.Style(self)
        style.configure("cb.Treeview.Heading", font=(None, 13))
        # put image on the right
        style.layout('cb.Treeview.Row',
                     [('Treeitem.row', {'sticky': 'nswe'}),
                      ('Treeitem.image', {'side': 'right', 'sticky': 'e'})])

        # use tags to set the checkbox state
        self.tag_configure('checked', image='checked')
        self.tag_configure('unchecked', image='unchecked')

    def tag_add(self, item, tags):
        new_tags = tuple(self.item(item, 'tags')) + tuple(tags)
        self.item(item, tags=new_tags)

    def tag_remove(self, item, tag):
        tags = list(self.item(item, 'tags'))
        tags.remove(tag)
        self.item(item, tags=tags)

    def insert(self, parent, index, iid=None, **kw):
        item = ttk.Treeview.insert(self, parent, index, iid, **kw)
        self.tag_add(item, (item, 'unchecked'))
        self.tag_bind(item, '<ButtonRelease-1>',
                      lambda event: self._on_click(event, item))

    def _on_click(self, event, item):
        """Handle click on items."""
        if self.identify_row(event.y) == item:
            if self.identify_column(event.x) == '#4': # click in 'Served' column
                # toggle checkbox image
                if self.tag_has('checked', item):
                    self.tag_remove(item, 'checked')
                    self.tag_add(item, ('unchecked',))
                else:
                    self.tag_remove(item, 'unchecked')
                    self.tag_add(item, ('checked',))



tree = CbTreeview(root, columns=("Table No.", "Order", "Time", "Served"),
                  height=400, selectmode="extended")

tree.heading('Table No.', text="Table No.", anchor='w')
tree.heading('Order', text="Order", anchor='w')
tree.heading('Time', text="Time", anchor='w')
tree.heading('Served', text="Served", anchor='w')
tree.column('#1', stretch='no', minwidth=0, width=100)
tree.column('#2', stretch='no', minwidth=0, width=600)
tree.column('#3', stretch='no', minwidth=0, width=100)
tree.column('#4', stretch='no', minwidth=0, width=70)

tree.pack(fill='both')

for i in range(5):
    tree.insert('', 'end', values=(i, i, i))
root.mainloop()

【讨论】:

  • 是否可以在不同的列中添加多个复选框?
  • @Jmm86 不,不使用此解决方案,因为我使用项目的图像来创建复选框,而一个项目只有一个图像。
  • @Jmm86 你可以做的是placettk.Checkbutton 在给定的单元格中使用tree.bbox(item, column) 来获取它的坐标。
  • 图像checkedunchecked 是内置的还是程序员必须在Gimp 中创建它们?当父母有一些但不是所有孩子checked时,是否有halfchecked图像?
  • @WinEunuuchs2Unix 如果你想要一个树形结构(不是像这里的表格),它会更适合查看stackoverflow.com/questions/5104330/…(或使用ttkwidgets中的CheckboxTreeview)部分选中的框。在这两种情况下,复选框都是用图片制作的,但在这个答案中,我从字符串(tk.PhotoImage(..., data=&lt;img data&gt;))加载它们,以使代码更容易为任何人运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
  • 2020-10-17
  • 2019-12-20
  • 2020-06-22
  • 1970-01-01
  • 2019-06-07
  • 2012-05-04
相关资源
最近更新 更多