Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Una cuestión sobre ttk.tree
#1
Sabemos que este widget puede presentar datos en formato tabla. Por una parte tengo la cabecera y por otro las filas, donde muestro los resultados del cursor de consultas a una base de datos. Hasta aqui todo bien.

Quiero ordenar los datos picando sobre la cabecera del tree, y de hecho recibo los resultados de un query tipo "SELECT * FROM mi_tabla ORDER BY campo_1". Picando en la cabecera de cada columna me muestra los datos ordenados por el campo que quiero,

El problema es que con cada consulta nueva me refresca tambien la cabecera, quedando muy feo, el parpadeo que produce.

Adjunto el fichero de prueba (nota: no me deja) que he fabricado emulando la respuesta de una query SELECT, generando 500.000 registros (se puede cambiar el num. de tuplas). Es muy caro en tiempo y recursos de memoria la ordenación de la lista de tuplas (los registros de la BD) por el campo soliticitado con 

Código:
l_ordenada = sorted(lista, key=lambda tup: tup[elem_tupla])

Es la segunda vez que utilizo este widget. Habia pensado en dividir el frame padre en dos subframes donde colocar: en el subframe de arriba la cabecera y en el subrame de abajo las filas registros. Asi, en principio, no parpadearía la cabecera con cada peitición de SELECT ORDER

sería algo así:

La cabecera:

Código:
self.arbol_sup= ttk.Treeview(self.frm_sup)

# creo las cabeceras - la columna 0 esta puesta a ancho 0
        self.arbol_sup.heading('#0', text='', anchor='w')
        self.arbol_sup.heading('#1', text='Campo 1
        ....

Las filas:

Código:
self.arbol_inf= ttk.Treeview(self.frm_sup)

#creo los indices de las columnas
        self.arbol_inf["columns"] = ("campo1", ...)
        self.arbol_inf.column("#0",...)
        self.arbol_inf.column("campo1",...)

y luego las lambdas de la cabecera ligarlas exclusivamente al arbol inferior.

Alquien que tenga más experiencia que yo, y me pueda aconsejar.

Gracias

pdta.: el archivo está en :

https://drive.google.com/file/d/0B2mK6w2...sp=sharing
Responder
#2
Hola, ¿cómo estás?

He probado tu código pero no observar el parpadeo que mencionas:

[Imagen: l8ddWtV.gif]

¿En qué sistema operativo estás corriendo el código?

Saludos
¡No te pierdas nuestro curso oficial en Udemy para aprender Python, bases de datos SQL, orientación a objetos, tkinter y mucho más!

También ofrecemos consultoría profesional de desarrollo en Python para personas y empresas.
Responder
#3
en el ejemplo que he enviado no parpadea, porque la ordenación de la lista de tuplas la hago en memoria. Es una simple simulación, para calcular tiempos, para luego (que es una aplicación en postgresql) aplcarla en real y que puede llegar a tener algunos cientos de miles de registros.

la función en serio es :

Código:
def get_cursor(nom, orden, queue):
            xxx = interfaz_pg.GestionBD(nom)
            cursor = xxx.muestra_todas_partidas(orden)
            queue.put(cursor)
        
ret = queue.Queue()   #para obtener un valor de retorno del thread
hilo_1 = threading.Thread(
        target=get_cursor,
        args=(nom_bd, campo_orden, ret,)
        )
hilo_1.start()
hilo_1.join()
     
lista_par = ret.get()

el cursor se obtiene de un metodo en otro modulo que ataca el postgresql, tal que asi

Código:
def muestra_todas_partidas(self, orden):
        consulta = "SELECT * FROM tb_tabla1 ORDER BY " + orden
        saca_par = self.conex.prepare(consulta)
        
        # lo transformo en una tupla de listas(filas)
        cursor = saca_par.declare()
        lista_par = cursor.read()
        #cursor.close()
        return lista_par

el problema, es que en este caso con una bd real, tengo que refrescar todo el ttk.tree, y no solo ordenar en memoria la lista de tuplas con,  p.ej.:

Código:
      lista_ordenada = sorted(l_par, key=lambda tup: tup[elem_tupla])

Imaginemonos que tenemos 5 millones de registros... Esto no sería manejable en memoria en un ordenador normal.

no se si me he explicado..., pero es que enviar solo el modulo real, sin todo el "acompañamiento" , no va a aclarar mucho.

Si hubiera algun modo de borrar solo las self.tree.column; pero he buscado y no he visto nada que merezca la pena.

Se me olvidaba.... Escribo en windows 10, 1 procesador 2 cores; y compruebo en linux debian 9, 1 procesador 2 cores; porque lo que tengo que hacer tiene que ser compatible por conveniencia/casi obligación. La presentación será con una máquina seria con 5 cores, pero tengo que programar para el peor de los casos.

gracias por tu rápida contestación
Responder
#4
ya está solucionado. no hay como dormir bien Smile)

sobre el ejemplo que puse ayer transpongo las modificaciones

linea 165:

Código:
def proceso_ordena(campo_orden):
            nombre_bd = 'bd_Temporal'
            proceso_col=multiprocessing.Process(target=ordena_lista, args=(nombre_bd, campo_orden, queue_tree))
            proceso_col.start()
            ordena_column(queue_tree.get())

linea 218:
Código:
#proceso_col=multiprocessing.Process(target=ordena_column, args=(l_tup, 0, queue_tree))
        #proceso_col.start()
        #ordena_column(queue_tree.get())
ordena_column(l_tup)

linea 245:
Código:
#def ordena_lista(l_par, elem_tupla, q):
def ordena_lista(nom_bd, orden, q):
    #l_ordenada = sorted(l_par, key=lambda tup: tup[elem_tupla])
    print(248, nom_bd)
    yyy = interfaz_pg.GestionBD(nom_bd)
    cursor = yyy.muestra_todas_partidas(orden)
    #q.put(l_ordenada)
    q.put(cursor)

obviamente he tenido que importar modulos propios que no vienen al caso, con lo que el main quedaría asi:

Código:
if __name__ == "__main__":
    raiz = Tk()
    raiz.geometry('1000x500+100+100')
    raiz.title('Prueba Tree y ordenacion de listas')
    
    ini_cl = 0
    xxx = sistema.Sistema()
    ini_cl = xxx.inicia_cluster()
    
    if ini_cl != 0:
        mp = ErrorCluster(root)
    else:
        mp = ClasePrueba(raiz)
  
    raiz.mainloop()

Si lo considerais oportuno podeis cerrar el hilo. Gracias por vuestra ayuda.
Responder
#5
Perfecto, me alegro que lo hayas resuelto. Saludos.
¡No te pierdas nuestro curso oficial en Udemy para aprender Python, bases de datos SQL, orientación a objetos, tkinter y mucho más!

También ofrecemos consultoría profesional de desarrollo en Python para personas y empresas.
Responder


Salto de foro:


Usuarios navegando en este tema: 2 invitado(s)