sorting the treeview tkinter column without clicking on the column header
Question:
I am writing a program where there is a customer record log. The program has the ability to enter the time and the client. This data is stored in the database. I can’t sort the time without clicking on the column header. I wanted that when entering the time and the name of the client, and clicking on the save button, the time was sorted. I get the time, sort it, but the move() method does not move the elements to the positions I need.
This is part of the code. In the sort_time() method, I’m trying to sort the time.
import tkinter as tk
from tkinter import ttk
from tkinter import *
import time
from datetime import datetime
class Main(tk.Frame):
def __init__(self, root):
super().__init__(root)
self.create_calendar()
self.create_journal()
self.create_button()
def create_calendar(self):
self.journal_frame = tk.Frame(self, borderwidth=1,
highlightthickness=5, highlightbackground='red')
self.journal_frame.grid(row=0, column=0, sticky='ns')
self.button_frame = tk.Frame(self, borderwidth=1,
highlightthickness=5, highlightbackground='red')
self.button_frame.grid(row=1, column=0)
def insert(self):
self.tree.insert('', END, values=(self.c_time.get(),
self.e_fio.get()))
def sort_time(self):
time = [(self.tree.set(i,0), i) for i in
self.tree.get_children('')]
spisok_time = [time[x][0] for x in range(len(time))]
sorted_spisok = sorted(spisok_time, key=lambda y:
datetime.strptime(y, '%H:%M'))
spisok_new_time = [(sorted_spisok[z], str(z+1)) for z in
range(len(sorted_spisok))]
for index, (val, k) in enumerate(spisok_new_time):
self.tree.move(k, '', index)
def create_journal(self):
columns = ('time', 'client')
self.tree = ttk.Treeview(self.journal_frame, columns=columns,
show='headings')
self.tree.grid(row=0,column=0)
self.tree.heading('time', text='Time', anchor='center')
self.tree.heading('client', text='Client', anchor='center')
self.tree.column('#1', width=50, stretch=True, anchor='e')
self.tree.column('#2', width=250, stretch=False,
anchor='center')
def create_button(self):
self.b_sort = tk.Button(self.journal_frame, text='Sort',
command=self.sort_time)
self.b_sort.grid(row=1, column=3, sticky='e')
self.l_time = tk.Label(self.button_frame, text='Time:')
self.l_time.grid(row=0, column=0, sticky='w')
time = ['8:00', '8:30', '9:00', '9:30', '10:00', '10:30',
'11:00', '11:30',
'12:00', '12:30', '13:00', '13:30', '14:00',
'14:30', '15:00', '15:30',
'16:00', '16:30', '17:00', '17:30', '18:00', '18:30',
'19:00', '19:30']
self.c_time = ttk.Combobox(self.button_frame, values=time,
width=5)
self.c_time.grid(row=0, column=1)
self.l_fio = tk.Label(self.button_frame, text='Name:')
self.l_fio.grid(row=1, column=0, sticky='w')
self.e_fio = tk.Entry(self.button_frame, width=20)
self.e_fio.grid(row=1, column=1)
self.b_save = tk.Button(self.button_frame, text='Save',
command=self.insert)
self.b_save.grid(row=5, column=1, sticky='e')
if __name__ == '__main__':
root = tk.Tk()
win = Main(root)
win.pack()
root.title('Вывод данных')
root.geometry('1500x800+100+100')
root.mainloop()
Answers:
In the sort_time()
, you sorted only timestamps into the sorted_spisok
, lost the information on the order of item identifiers, and put arbitrary identifiers into the spisok_new_time
.
So, sort the entire rows including item identifiers like this.
...
def sort_time(self):
rows = [(self.tree.set(i,0), i) for i in
self.tree.get_children('')]
sorted_rows = sorted(rows, key=lambda row:
datetime.strptime(row[0], '%H:%M'))
for index, (_, id) in enumerate(sorted_rows):
self.tree.move(id, '', index)
...
I am writing a program where there is a customer record log. The program has the ability to enter the time and the client. This data is stored in the database. I can’t sort the time without clicking on the column header. I wanted that when entering the time and the name of the client, and clicking on the save button, the time was sorted. I get the time, sort it, but the move() method does not move the elements to the positions I need.
This is part of the code. In the sort_time() method, I’m trying to sort the time.
import tkinter as tk
from tkinter import ttk
from tkinter import *
import time
from datetime import datetime
class Main(tk.Frame):
def __init__(self, root):
super().__init__(root)
self.create_calendar()
self.create_journal()
self.create_button()
def create_calendar(self):
self.journal_frame = tk.Frame(self, borderwidth=1,
highlightthickness=5, highlightbackground='red')
self.journal_frame.grid(row=0, column=0, sticky='ns')
self.button_frame = tk.Frame(self, borderwidth=1,
highlightthickness=5, highlightbackground='red')
self.button_frame.grid(row=1, column=0)
def insert(self):
self.tree.insert('', END, values=(self.c_time.get(),
self.e_fio.get()))
def sort_time(self):
time = [(self.tree.set(i,0), i) for i in
self.tree.get_children('')]
spisok_time = [time[x][0] for x in range(len(time))]
sorted_spisok = sorted(spisok_time, key=lambda y:
datetime.strptime(y, '%H:%M'))
spisok_new_time = [(sorted_spisok[z], str(z+1)) for z in
range(len(sorted_spisok))]
for index, (val, k) in enumerate(spisok_new_time):
self.tree.move(k, '', index)
def create_journal(self):
columns = ('time', 'client')
self.tree = ttk.Treeview(self.journal_frame, columns=columns,
show='headings')
self.tree.grid(row=0,column=0)
self.tree.heading('time', text='Time', anchor='center')
self.tree.heading('client', text='Client', anchor='center')
self.tree.column('#1', width=50, stretch=True, anchor='e')
self.tree.column('#2', width=250, stretch=False,
anchor='center')
def create_button(self):
self.b_sort = tk.Button(self.journal_frame, text='Sort',
command=self.sort_time)
self.b_sort.grid(row=1, column=3, sticky='e')
self.l_time = tk.Label(self.button_frame, text='Time:')
self.l_time.grid(row=0, column=0, sticky='w')
time = ['8:00', '8:30', '9:00', '9:30', '10:00', '10:30',
'11:00', '11:30',
'12:00', '12:30', '13:00', '13:30', '14:00',
'14:30', '15:00', '15:30',
'16:00', '16:30', '17:00', '17:30', '18:00', '18:30',
'19:00', '19:30']
self.c_time = ttk.Combobox(self.button_frame, values=time,
width=5)
self.c_time.grid(row=0, column=1)
self.l_fio = tk.Label(self.button_frame, text='Name:')
self.l_fio.grid(row=1, column=0, sticky='w')
self.e_fio = tk.Entry(self.button_frame, width=20)
self.e_fio.grid(row=1, column=1)
self.b_save = tk.Button(self.button_frame, text='Save',
command=self.insert)
self.b_save.grid(row=5, column=1, sticky='e')
if __name__ == '__main__':
root = tk.Tk()
win = Main(root)
win.pack()
root.title('Вывод данных')
root.geometry('1500x800+100+100')
root.mainloop()
In the sort_time()
, you sorted only timestamps into the sorted_spisok
, lost the information on the order of item identifiers, and put arbitrary identifiers into the spisok_new_time
.
So, sort the entire rows including item identifiers like this.
...
def sort_time(self):
rows = [(self.tree.set(i,0), i) for i in
self.tree.get_children('')]
sorted_rows = sorted(rows, key=lambda row:
datetime.strptime(row[0], '%H:%M'))
for index, (_, id) in enumerate(sorted_rows):
self.tree.move(id, '', index)
...