ttk treeview:交替行颜色

Posted

技术标签:

【中文标题】ttk treeview:交替行颜色【英文标题】:ttk treeview: alternate row colors 【发布时间】:2011-12-14 06:58:51 【问题描述】:

如何为treeview 小部件设置样式,以便交替行具有不同的背景颜色,例如,第 1、3、5 行具有白色背景,而第 2、4、6 行具有浅蓝灰色背景?

我还想设置gridlines

【问题讨论】:

【参考方案1】:

工作代码:python3.6

try:
    from Tkinter import *
    from ttk import *
except ImportError:  # Python 3
    from tkinter import *
    from tkinter.ttk import *

class App(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.CreateUI()
        self.LoadTable()
        self.grid(sticky = (N,S,W,E))
        parent.grid_rowconfigure(0, weight = 1)
        parent.grid_columnconfigure(0, weight = 1)

    def CreateUI(self):
        style = Style(self)
        
        style.theme_use("clam")
        style.configure("Treeview.Heading", background="black", foreground="white")        
        
        style.configure("Treeview",
                        background = "silver",
                        foreground = "black",
                        rowheight = 25,
                        fieldbackground = "silver",                
                        )
        style.map('Treeview', background=[('selected', 'green')])

        
        tv = Treeview(self)
        tv['columns'] = ('filename', 'environment', 'status')
        tv.heading("#0", text='Job Id')
        tv.column("#0", anchor="w", width=100)
        tv.heading('filename', text='File Name')
        tv.column('filename', anchor='w')
        tv.heading('environment', text='Environment')
        tv.column('environment', anchor='w', width=100)
        tv.heading('status', text='Status')
        tv.column('status', anchor='w', width=100)        
        tv.grid(sticky = (N,S,W,E))
        self.treeview = tv
        self.grid_rowconfigure(0, weight = 1)
        self.grid_columnconfigure(0, weight = 1)
        
        

    def LoadTable(self):
        self.treeview.tag_configure('oddrow', background = "#D3D3D3")
        self.treeview.tag_configure('evenrow', background = "#000000")
        self.treeview.insert('', 'end', text="First", iid=0,values=('10:00',
                             '10:10', 'Ok'), tags=('oddrow'))
        
        self.treeview.insert('', 'end', text="First", iid=1,values=('10:00',
                             '10:10', 'Ok'), tags=('evenrow'))

def main():
    root = Tk()
    App(root)
    root.mainloop()

if __name__ == '__main__':
    main()

【讨论】:

【参考方案2】:

无需任何额外模块即可运行...可能会弄乱代码以使其与您自己的代码一起使用。

from Tkinter import *
import ttk

class Test(Frame):

    def __init__(self):
        Frame.__init__(self)
        self.pack()
        self.listbox()
        self.buttons()

    def listbox(self):
        global new_customer_lb

        scrollbar = Scrollbar(self, orient="vertical")
        new_customer_lb = ttk.Treeview(self, columns=('ID','First Name','Last Name'))
        new_customer_lb['show']='headings'
        new_customer_lb.heading('#1', text= 'ID')
        new_customer_lb.column('#1', width=50, stretch=NO)
        new_customer_lb.heading('#2', text= 'First Name')
        new_customer_lb.column('#2', width=100, stretch=NO)
        new_customer_lb.heading('#3', text= 'Last Name')
        new_customer_lb.column('#3', width=100, stretch=NO)
        new_customer_lb.configure(yscroll = scrollbar.set, selectmode="browse")
        scrollbar.config(command=new_customer_lb.yview)
        new_customer_lb.pack()


    def buttons(self):
        load = Button(self, text='show customers', command=lambda:self.load_working_customers())
        test = Button(self, text='test new colors', command=lambda:self.test_colors())
        load.pack()
        test.pack()

    def load_working_customers(self):
        new_customer_lb.delete(*new_customer_lb.get_children())
        for a in range(0,10):            
            new_customer_lb.insert('','end', values=(a,'first','last'))

    def test_colors(self):
        new_customer_lb.delete(*new_customer_lb.get_children())                 

        new_customer_lb.tag_configure("evenrow",background='white',foreground='black')
        new_customer_lb.tag_configure("oddrow",background='black',foreground='white')
        for a in range(0,10):            
            if a % 2 == 0:
                new_customer_lb.insert('','end', values=(a,'first','last'), tags=('evenrow',))
            if a % 2 != 0:
                new_customer_lb.insert('','end', values=(a,'first','last'), tags=('oddrow',))

root = Tk()
app = Test()
app.mainloop()

【讨论】:

'a' 已经是一个数字,它更容易使用 %。如果您没有带有数字的列,您可以使用数字填充列并使其隐藏,然后使用隐藏的列号附加标签。还有每行自动放置的 iid,但我个人还没有想出将 iid 放入 int() 形式以使用 % 。 不运行:./demo3.py:第 1 行:from:找不到命令 ./demo3.py:第 2 行:导入:找不到命令 ./demo3.py:第 4 行:意外标记附近的语法错误(' ./demo3.py: line 4: class Test(Frame):'【参考方案3】:

这是创建一个 SQL 数据库。然后将少数客户从 db 加载到列表框中。 然后您可以单击测试新颜色按钮以显示它为奇数行更改颜色。只要您将 sqlalchemy 作为模块安装,它就可以运行。

from Tkinter import *
import ttk
from sqlalchemy import Column, ForeignKey, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

base = declarative_base()


class Customer(base):
    __tablename__='Customer_Details'
    Id = Column(Integer, primary_key=True)
    first_name = Column(String(64))
    last_name = Column(String(64))


class DB_connection(object):
    def __enter__(variable):
        variable.engine = create_engine("sqlite:///example.db")
        base.metadata.bind = variable.engine
        variable.DBSession = sessionmaker(bind=variable.engine)
        variable.Session = variable.DBSession
        variable.session = variable.Session()
        return variable
    def __exit__(variable, exc_type, exc_val, exc_tb):
        variable.session.commit()
        variable.session.close()

class Test(Frame):

    def __init__(self):
        Frame.__init__(self)
        self.pack()
        self.listbox()
        self.buttons()

    def listbox(self):
        global new_customer_lb

        scrollbar = Scrollbar(self, orient="vertical")
        new_customer_lb = ttk.Treeview(self, columns=('ID','First Name','Last Name'))
        new_customer_lb['show']='headings'
        new_customer_lb.heading('#1', text= 'ID')
        new_customer_lb.column('#1', width=50, stretch=NO)
        new_customer_lb.heading('#2', text= 'First Name')
        new_customer_lb.column('#2', width=100, stretch=NO)
        new_customer_lb.heading('#3', text= 'Last Name')
        new_customer_lb.column('#3', width=100, stretch=NO)
        new_customer_lb.configure(yscroll = scrollbar.set, selectmode="browse")
        scrollbar.config(command=new_customer_lb.yview)
        new_customer_lb.pack()


    def buttons(self):
        db = Button(self, text='make DB', command=lambda:self.create_db())
        customer = Button(self, text='create customers', command=lambda:self.create_customers())
        load = Button(self, text='show customers', command=lambda:self.load_working_customers())
        test = Button(self, text='test new colors', command=lambda:self.test_colors())
        db.pack()
        customer.pack()
        load.pack()
        test.pack()

    def create_db(self):
        print("start create db function")
        engine = create_engine('sqlite:///example.db')
        base.metadata.create_all(engine)
        print("Success create db function")

    def create_customers(self):
        print ('Start add customer sql')
        customer1 = Customer(first_name='first1',last_name='last1')
        customer2 = Customer(first_name='first2',last_name='last2')
        customer3 = Customer(first_name='first3',last_name='last3')
        customer4 = Customer(first_name='first4',last_name='last4')
        with DB_connection() as DB:
            DB.session.add_all([customer1,customer2,customer3,customer4])
        print ('sucess add customer sql')

    def load_working_customers(self):
        new_customer_lb.delete(*new_customer_lb.get_children())    
        with DB_connection() as DB:
            for a,b,c in DB.session.query(Customer.Id,Customer.first_name,Customer.last_name).order_by(Customer.Id):
                new_customer_lb.insert('','end', values=(a,b,c))

    def test_colors(self):
        new_customer_lb.delete(*new_customer_lb.get_children())                 

### configure even and odd here
        new_customer_lb.tag_configure("evenrow",background='white',foreground='black')
        new_customer_lb.tag_configure("oddrow",background='black',foreground='white')

        with DB_connection() as DB:
## this loop will take 'a' (Customer.Id) and test if even or odd
            for a,b,c in DB.session.query(Customer.Id,Customer.first_name,Customer.last_name).order_by(Customer.Id):                
                if a % 2 == 0:
                    new_customer_lb.insert('','end', values=(a,b,c), tags=('evenrow',))
                else:
                    new_customer_lb.insert('','end', values=(a,b,c), tags=('oddrow',))

root = Tk()
app = Test()
app.mainloop()

【讨论】:

【参考方案4】:

我意识到这是一个老问题,但只是为了记录在创建树之后配置标签(即尚未添加任何项目时)也可以。随着项目稍后被插入,它们将被赋予适合其“奇数”或“偶数”标签的背景颜色。

【讨论】:

我认为Colin的意思是可以先配置标签,然后添加行,行会被着色。正如马特的回答所暗示的那样,添加所有行后无需配置标签。【参考方案5】:

几个月前我也遇到过同样的问题。

来自tk docs:

You can assign a list of tags to each item using the "tags" 
item configuration option (again, when creating the item or later on).

Tag configuration options can then be specified, which will then 
apply to all items having that tag.

基本上,您将一个标签应用于所有奇数行,一个不同的标签应用于每个偶数行,然后配置标签。


在树视图中创建项目时,为它们添加标签:

tree.insert('', 'end', text = 'your text', tags = ('oddrow',))

此代码在tree 中创建一个元素,tags 参数将标签“oddrow”分配给该元素。

用“oddrow”和“evenrow”标签创建所有元素后,您可以为标签着色:

tree.tag_configure('oddrow', background='orange')
tree.tag_configure('evenrow', background='purple')

【讨论】:

您有任何示例代码或更多信息吗?我无法从文档中的描述中弄清楚如何实现。 谢谢。现在,如果我们能弄清楚如何添加网格线...... :) 我可能会有相关问题。如果是这样,我会开始一个新的话题。 如何在不使用标签的情况下更改特定行的颜色? iid可以吗?我有一个带有目录树的树视图,我需要更改特定行的颜色,当它被选中并单击一个按钮时。

以上是关于ttk treeview:交替行颜色的主要内容,如果未能解决你的问题,请参考以下文章

GtkTreeView 交替行颜色

如何使 ttk.Treeview 的行可编辑?

Python如何改变tkinter.ttk.Treeview表格组件的每行的行高?

tkinter ttk treeview 如何设置固定宽度?为啥它会随着列数而变化?

ttk.Treeview

ttk.Treeview - 无法更改行高