ttk treeview: альтернативные цвета строк

#python #tkinter #treeview #ttk

#python #tkinter #просмотр дерева #ttk

Вопрос:

Как я могу установить стиль для treeview виджетов, чтобы альтернативные строки имели разные цвета фона, например, строки 1,3,5 имеют белый фон, а строки 2,4,6 имеют светло-сине-серый фон?

Я также хотел бы установить gridlines .

Ответ №1:

У меня была такая же проблема несколько месяцев назад.

Из документации tk:

 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.
  

По сути, вы применяете один тег ко всем строкам с нечетными номерами, другой тег к каждой из четных строк, а затем настраиваете теги.


Когда вы создаете элементы внутри treeview, добавляйте к ним теги:

 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')
  

Комментарии:

1. У вас есть какой-либо пример кода или дополнительная информация? Я не могу понять, как реализовать из описания в документах.

2. Спасибо. Теперь, если мы можем просто выяснить, как добавить линии сетки … 🙂

3. Вероятно, у меня возникнут связанные с этим вопросы. Если это так, я начну новую тему.

4. Как изменить цвет определенной строки без использования тегов? Возможно ли это с помощью iid? У меня есть treeview с деревом каталогов, мне нужно изменить цвет определенной строки, когда она выбрана, и нажать кнопку.

Ответ №2:

Я понимаю, что это старый вопрос, но просто для записи настройка тегов сразу после создания дерева (т. Е. Когда в него еще не добавлены элементы) также работает. Когда элементы будут вставлены позже, им будет присвоен цвет фона, соответствующий их тегу ‘oddrow’ или ‘evenrow’.

Комментарии:

1. Я думаю, Колин имел в виду, что вы можете сначала настроить теги, затем добавить строки, и строки будут окрашены. Нет необходимости настраивать теги после добавления всех строк, как следует из ответа Мэтта.

Ответ №3:

это можно запустить без каких-либо дополнительных модулей … может испортить код, чтобы заставить его работать с вашим собственным.

 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()
  

Комментарии:

1. когда ‘a’ уже является числом, проще использовать%. в случае, если у вас нет столбца с числами, вы можете заполнить столбец числами и сделать его скрытым, а затем использовать скрытые номера столбцов для прикрепления тегов. также есть iid, который автоматически помещается в каждую строку, но я лично не понял, как перевести iid в форму int(), чтобы использовать% с.

2. Не выполняется: ./demo3.py : строка 1: из: команда не найдена ./demo3.py : строка 2: импорт: команда не найдена./demo3.py : строка 4: синтаксическая ошибка рядом с неожиданным (' ./demo3.py: line 4: тестом класса токена (фрейм): ‘

Ответ №4:

Это делается для создания базы данных SQL. затем загружает несколько клиентов из базы данных в listbox. затем вы можете нажать кнопку проверить новые цвета, чтобы показать, что она меняет цвета для нечетных строк. это можно выполнить, если у вас установлена 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()
  

Ответ №5:

рабочий код: 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()
  

Ответ №6:

Я создал функцию, которая применяет чередующийся цвет строк. Это лучший способ для тех, кто использует строки и нуждается в повторном правильном перекрашивании.

 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)