Reputation: 7898
How can I set a style for treeview
widgets so that alternate rows have different background colors, for example, rows 1,3,5 have white backgrounds and rows 2,4,6 have light blue-grey backgrounds?
I'd also like to set gridlines
.
Upvotes: 20
Views: 38839
Reputation: 31
I updated it a little bit better, and this is working with later versions of python 3.9+, maybe older.
This will sort and you can just ad the call to it in your function to update your treeview as well as your sort function at the base and it will keep it after sorting.
def apply_striped_row_color(tree, oddcolor='lightgray', evencolor='white'):
for index, iid in enumerate(tree.get_children()):
if index % 2 == 0:
tree.item(iid, tags=('evenrow',))
else:
tree.item(iid, tags=('oddrow',))
tree.tag_configure('oddrow', background=oddcolor)
tree.tag_configure('evenrow', background=evencolor)
Upvotes: 0
Reputation: 634
I made a function that applies alternating row color. This is a better way for those who are resorting the rows and need to recolor correctly again.
def apply_striped_row_color(tv, oddcolor='lightgray', evencolor='white'):
for index, iid in enumerate(tv.get_children()):
tags = tv.item(iid,'tags') # get current tags
tags.remove('evenrow') if 'evenrow' in tags else None # remove if exist
tags.remove('oddrow') if 'oddrow' in tags else None # remove if exist
tags.append('evenrow' if index%2 else 'oddrow')
self.item(iid, tags=tags)
tv.tag_configure('oddrow', background=oddcolor)
tv.tag_configure('evenrow', background= evencolor)
Upvotes: 0
Reputation: 898
working code: 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()
Upvotes: 0
Reputation: 53
this is runnable without any extra modules... could mess with the code to make it work with your own.
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()
Upvotes: 1
Reputation: 53
This is to create a SQL db. then loads the few customers from db into listbox. then you can click test new colors button to show it changing colors for odd rows. this is runnable as long as you have sqlalchemy installed as module.
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()
Upvotes: 0
Reputation: 31
I realise this is an old question but just for the record configuring the tags just after creating the tree (i.e. when no items have yet been added to it) also works. As items get inserted later on they will be given the background colour appropriate to their 'oddrow' or 'evenrow' tag.
Upvotes: 3
Reputation: 49085
I had this same issue a few months ago.
From the 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.
Basically, you apply one tag to all of the odd-numbered rows, a different tag to each of the even-numbered rows, and then configure the tags.
When you create the items inside the treeview, add tags to them:
tree.insert('', 'end', text = 'your text', tags = ('oddrow',))
This code creates an element in tree
, and the tags
argument assigns the tag 'oddrow' to the element.
Once you've created all your elements with 'oddrow' and 'evenrow' tags, you can color the tags:
tree.tag_configure('oddrow', background='orange')
tree.tag_configure('evenrow', background='purple')
Upvotes: 54