Pregunta

Estoy tratando de utilizar el ttk.Treeview de ordenación de la función se ilustra en la respuesta a esta pregunta (Tk treeview de clasificación de la columna) y funciona muy bien para cadenas como 'abc', 'bcd', 'cde", etc., pero cuando trato de ordenar los números que se termina mostrando como esta:

1
10
11
2
3
...

Me gustaría que los datos se ordenan para que la salida es:

1
2
3
...
10
11

Sé que los valores en la vista de árbol de las columnas son las cadenas y de las que estoy más probabilidades de ir a la necesidad de convertir a enteros antes de la clasificación, pero no puedo averiguar cómo hacerlo.

¿Fue útil?

Solución

list.sort método, sorted la función de aceptar opcional key parámetro.El valor de retorno de la función se utiliza como clave de comparación.

Especificar key la función que convertir el elemento de vista de árbol en el número va a resolver su problema.

Ejemplo:

try:
    from tkinter import *
    from tkinter import ttk
except ImportError:
    from Tkinter import *
    import ttk

def treeview_sort_column(tv, col, reverse):
    l = [(tv.set(k, col), k) for k in tv.get_children('')]
    l.sort(key=lambda t: int(t[0]), reverse=reverse)
    #      ^^^^^^^^^^^^^^^^^^^^^^^

    for index, (val, k) in enumerate(l):
        tv.move(k, '', index)

    tv.heading(col,
               command=lambda: treeview_sort_column(tv, col, not reverse))

root = Tk()
columns = ('number',)
treeview = ttk.Treeview(root, columns=columns, show='headings')
for t in ('1', '10', '11', '2', '3'):
    treeview.insert('', END, values=(t,))
treeview.pack()
for col in columns:
    treeview.heading(col, text=col,
                     command=lambda c=col: treeview_sort_column(treeview, c, False))

mainloop()

enter image description here

Otros consejos

I figure I'd add this bit of code for anyone wanting to use the above solution for both regular string sorts and numeric sorts.

def treeview_sort_column(tv, col, reverse):
    l = [(tv.set(k, col), k) for k in tv.get_children('')]
    try:
        l.sort(key=lambda t: int(t[0]), reverse=reverse)
        #      ^^^^^^^^^^^^^^^^^^^^^^^
    except ValueError:
        l.sort(reverse=reverse)

    for index, (val, k) in enumerate(l):
        tv.move(k, '', index)

    tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))        

It took me a while to find a variant of this answer, but I thought I would post an answer for those looking to sort dates as a string (i.e. 'DD/MM/YYYY')

import datetime

def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
    l.sort(key=lambda: x, datetime.datetime.strptime(x[0], '%d/%m/%y'), reverse=reverse)

for index, (val, k) in enumerate(l):
    tv.move(k, '', index)

tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top