Topic: inserire i valori nei widget giusti al click del mouse sulla riga della tabella  (Letto 115 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Salve,
allego l'immagine dell'interfaccia grafica del mio programma in python per render la richiesta più comprensibile. So che al momento la grafica non è delle migliori ma voglio prima renderlo funzionale e poi pensare alle migliorie grafiche.

ora per modificare i valori nel db devo prima scrivere il numero della commessa nel widget commessa, poichè questo valore è necessario per scorrere il db e fermarsi alla riga giusta.

io vorrei che quando clicco sulla riga desiserata automaticamente il valore del widget commessa prende il valore del campo commessa della riga selezionata.

Spero di essere stato chiaro. Grazie in anticipo.


Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 657
  • Punti reputazione: 0
    • Mostra profilo
Domandina da 2M$ la Tua ;)

 alcune domande preliminari per poter cominciare a cercare di capire di cosa stai parlando :
1 - di quale framework grafico si tratta?
2 - quale è il widget che utilizzi per per rappresentare i dati in forma tabellare?
3 - i dati rappresentati sono memorizzati solo nel widget oppure in una data stuttura dati?
4 - nell'ambito della finestra in figura, quale e lo stato di visibilità tanto del widget "tabellare" quanto dell'eventuale struttura dati?

Le domande sopra sono solo per capire se chi risponde ha la possibilità o meno di darti una mano, in caso positivo poi verranno domande più mirate a cercare possibili soluzioni.

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Grazie @nuzzopippo...  ho usato tkinter posizionando la tabella con grid,
riporto la porzione di codice che popola la tabella, preleva i dati da un db , e metto anche i tre componenti che vorrei far aggiornare al click


cursore = db.cursor()
cursore.execute("SELECT * from tempo_lavorazioni")
risultato = cursore.fetchall()

colonne = ('numero_commessa', 'meccanico', 'inizio_lavoro', 'pausa_lavoro', 'riavvio_lavoro', 'fine_lavoro', 'stato', 'durata', 'note')
tabella = ttk.Treeview(root, columns=colonne, show='headings',height=18, selectmode='browse')
tabella.heading('numero_commessa', text='Commessa' )
tabella.column("numero_commessa", width = 80, anchor ='c')
tabella.heading('meccanico', text='Meccanico')
tabella.column("meccanico", width = 100, anchor ='c')
tabella.heading('inizio_lavoro', text='Iniziato')
tabella.column("inizio_lavoro", width = 160, anchor ='c')
tabella.heading('pausa_lavoro', text='Pausa')
tabella.column("pausa_lavoro", width = 160, anchor ='c')
tabella.heading('riavvio_lavoro', text='Riavviato')
tabella.column("riavvio_lavoro", width = 160, anchor ='c')
tabella.heading('fine_lavoro', text='Finito')
tabella.column("fine_lavoro", width = 160, anchor ='c')
tabella.heading('stato', text='Stato')
tabella.column("stato", width = 60, anchor ='c')
tabella.heading('durata', text='Tempo Totale riparazione')
tabella.column("durata", width = 200, anchor ='c')
tabella.heading('note', text='Informazioni sulla lavorazione')
tabella.column("note", width = 820, anchor ='w')


for riga in risultato:
    tabella.insert('', END, values=riga)

tabella.grid(row=0, column=0, sticky='nsew')


scrollbary = ttk.Scrollbar(root, orient=VERTICAL, command=tabella.yview)
scrollbary.grid(row=0, column=1, sticky='ns')
tabella.configure(yscrollcommand=scrollbary.set)

scrollbarx = ttk.Scrollbar(root, orient=HORIZONTAL, command=tabella.xview)
scrollbarx.grid(row=1, column=0, sticky='ew')
tabella.configure(xscrollcommand=scrollbarx.set)



i widget che avevo intenzione di popolare al click del mouse sono 3 una entry per la commessa, una entry per le info e una combobox per il nominativo

entry per il numero commessa:

label_commessa = Label(root, text="Commessa")
label_commessa.grid(row=3, column=0, padx=2, pady=2, sticky="w")

commessa = StringVar()
commessa_entry = ttk.Entry(root, textvariable=commessa)
commessa_entry.grid(row=4, column=0, padx=6, pady=6, ipadx=6, ipady=6, sticky="w")
commessa_entry.focus()


entry per le info:

label_info = Label(root, text="Informazioni sulla Lavorazione" )
label_info.grid(row=8, column=0, padx=2, pady=2)
informazioni = StringVar()
informazioni_entry = ttk.Entry(root, textvariable=informazioni)
informazioni_entry.grid(row=7, column=0 , ipadx=80, ipady=10)


combobox nominativo :

nominativo = StringVar()
nominativo_combobox = ttk.Combobox(root, textvariable=nominativo)
nominativo_combobox['values'] = ["Stefano","Mirko", "Andrea", "Mauro", "Roberto"]
nominativo_combobox['state'] = 'readonly'
nominativo_combobox.grid(row=4, column=0, ipadx=6, ipady=6, sticky="e")


 :fingers-crossed: :fingers-crossed: :fingers-crossed:

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 657
  • Punti reputazione: 0
    • Mostra profilo
Hai risposto ai punti 1 e 2 ma mancano indicazioni sui punti 3 e 4 ... anche se temo di conoscere la risposta.

tkinter e ttk.Treeview li conosco, trovando un po' di tempo sono in grado di farTi un esempio spicciolo sulla selezione di un elemento nella treeview con popolamento di altri widget, però io utilizzo di norma la programmazione ad oggetti mentre credo Tu utilizzi processi funzionali, è cosi?
Riguardo ai dati sembrerebbe che Tu Ti limiti ad esporli nella Treeview è così?

Rispondi a queste due domande ed abbi un po di pazienza (ho diverse cose da fare) che cerco di scrivere un piccolo esempio aderente al Tuo modo di implementare.

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Hai risposto ai punti 1 e 2 ma mancano indicazioni sui punti 3 e 4 ... anche se temo di conoscere la risposta.

tkinter e ttk.Treeview li conosco, trovando un po' di tempo sono in grado di farTi un esempio spicciolo sulla selezione di un elemento nella treeview con popolamento di altri widget, però io utilizzo di norma la programmazione ad oggetti mentre credo Tu utilizzi processi funzionali, è cosi?
Riguardo ai dati sembrerebbe che Tu Ti limiti ad esporli nella Treeview è così?

Rispondi a queste due domande ed abbi un po di pazienza (ho diverse cose da fare) che cerco di scrivere un piccolo esempio aderente al Tuo modo di implementare.

Grazie @nuzzopippo sempre sul pezzo   :batti5: ...
come avrai certamente capito sono un autodidatta ma con tanta voglia di imparare. Processi funzionali per "obbligo" non avendo una conoscenza più profonda del linguaggio al momento sono alla ricerca delle soluzioni che mi servono per risolvere problemi pratici che mi stimolano di più  lo studio e la ricerca di soluzioni .. Quando avrò un quadro più completo e una conoscenza più approfondita saprò dirti di che partito sono  ;)...
Riguardo i dati mi limito ad esporli nella TreeView semplicemente,  perchè ho bisogno solo di quello a livello di utilizzo finale ed è comunque  tutto salvato su db .... hai qualche miglioria da consigliarmi a riguardo?


Sempre molte grazie   :)

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 657
  • Punti reputazione: 0
    • Mostra profilo
...come avrai certamente capito sono un autodidatta ma con tanta voglia di imparare.
Si, l'avevo immaginato e valutato che stai cercando di darTi da fare, mi ricordi me stesso un po' di tempo fa ... intanto rispondiamo al quesito che hai posto, ossia : come ricavare ed esporre i dati selezionati nella Treeview?
Per farlo devi intercettare l'evento di variazione della selezione nell'ambito della tabella (fare il binding, in gergo) e definire una funzione di callback che effettui le opportune operazioni, ieri ho cominciato a scrivere un breve esempio, da poco concluso, che simula la tabella da Te prodotta, ed alcuni controlli dati e reagisce al cambio di selezione, per i dati ho creato un file di testo riportante alcuni dei dati da Te esposti:
NzP:~$ cat dati
8888;Mirco;2023-01-21 12:56:49;;;2023-01-21 12:56:54;C;;
7777;Andrea;2023-01-21 13:01:19;;;2023-01-21 13:01:25;C;;
545;Andrea;2023-01-21 13:16:59;2023-01-21 13:17:30;2023-01-21 13:17:30;2023-01-21 13:17:38;C;;Riavviato
654;Mirko;0000-00-00 00:00:00;;;0000-00-00 00:00:00;C;;
909;Andrea;0000-00-00 00:00:00;2023-01-22 22:25:10;2023-01-22 22:25:19;0000-00-00 00:00:00;C;;Riavviato
333;Mirko;0000-00-00 00:00:00;2023-01-22 22:42:12;2023-01-22 22:42:20;0000-00-00 00:00:00;C;;Riavviato
444;Mirko;0000-00-00 00:00:00;2023-01-22 22:53:45;2023-01-22 22:54:19;0000-00-00 00:00:00;C;;Riavviato
222;Mirko;0000-00-00 00:00:00;;;0000-00-00 00:00:00;A;;
1111;;2023-01-23 00:23:07;2023-01-23 00:30:38;2023-01-23 00:30:52;2021-01-23 00:27:13;R;;Riavviato
5555;Stefano;23-01-2023 00:40:27;;;23-01-2023 00:40:44;C;;
NzP:~$

Tale file che ho denominato "dati", senza estensione (in linux non serve), copiati i dati nella direttrice da dove lancerai lo script per fare la prova, se nomini diversamente il file adegua nella funzione "on_data"
Lo scrip esemplificativo è questo:
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk

col_ref = [['numero_commessa', 'Commessa', 80], ['meccanico', 'Meccanico', 100],
           ['inizio_lavoro', 'Iniziato', 160], ['pausa_lavoro', 'Pausa', 160],
           ['riavvio_lavoro', 'Riavviato', 160], ['fine_lavoro', 'Finito', 160],
           ['stato', 'Stato', 60], ['durata', 'Tempo Totale\nriparazione', 120],
           ['note', 'Informazioni sulla lavorazione', 520]]

# funzioni di callback
def on_data(evt=None):  # carica i dati da un file di testo
    with open('dati') as f:
        data = f.readlines()
    mecc = []
    for r in data:
        vals = r.rstrip('\n').split(';')
        mecc.append(vals[1])
        tbl.insert('', tk.END, values=vals)
    mecc = sorted(list(set(mecc)))
    cmb_mecc['values'] = mecc
    cmb:mecc.select_set(0)
    bt_data.configure(state='disabled')

def on_select(evt):  # espone i dati selezionati nella treeview
    #print(tbl.item(tbl.focus()))
    data = tbl.item(tbl.focus())['values']
    if not data: return
    e_comm.delete(0, tk.END)
    e_comm.insert(tk.END, str(data[0]))
    v_state.set(data[6])
    e_date.delete(0, tk.END)
    match data[6]:
        case 'A':
            e_date.insert(tk.END, data[2])
        case 'P':
            e_date.insert(tk.END, data[3])
        case 'R':
            e_date.insert(tk.END, data[4])
        case 'C':
            e_date.insert(tk.END, data[5])
        case _:
            pass
    cmb_mecc.set(data[1])
    e_note.delete(0, tk.END)
    e_note.insert(tk.END, data[8])   
   
# sbrigativa creazione della GUI
root = tk.Tk()
cols = [x[0] for x in col_ref]  # se oscuro vedere le comprehension's
tbl = ttk.Treeview(root, columns=cols, show='headings',
                   height=10, selectmode='browse')
tbl.heading('#0', text='\n\n')
tbl.grid(row=0, column=0, sticky='nsew')
for c in col_ref:
    if c[0] != 'note':
        tbl.heading(c[0], text=c[1])
        tbl.column(c[0], width=c[2], anchor='c', stretch=tk.NO)
    else:
        tbl.heading(c[0], text=c[1])
        tbl.column(c[0], minwidth=c[2], anchor='c')       
vscroll = ttk.Scrollbar(root, orient=tk.VERTICAL, command=tbl.yview)
vscroll.grid(row=0, column=1, sticky='ns')
tbl.configure(yscrollcommand=vscroll.set)
hscroll = ttk.Scrollbar(root, orient=tk.HORIZONTAL, command=tbl.xview)
hscroll.grid(row=1, column=0, sticky='ew')
tbl.configure(xscrollcommand=hscroll.set)
pn_data = tk.Frame(root)  # pannello per dati
pn_data.grid(row=2, column=0, columnspan=2, sticky='ew')
lbl = tk.Label(pn_data, text='Commessa :')
lbl.grid(row=0, column=0, padx=6, pady=6, sticky='w')
e_comm = tk.Entry(pn_data, width=5)
e_comm.grid(row=0, column=1, padx=6, pady=6, sticky='w')
lbl = tk.Label(pn_data, text='Stato :')
lbl.grid(row=0, column=2, padx=6, pady=6, sticky='w')
v_state = tk.StringVar(root)
r_a = tk.Radiobutton(pn_data, text='Aperta', variable=v_state, value='A')
r_a.grid(row=0, column=3, padx=6, pady=6, sticky='w')
r_p = tk.Radiobutton(pn_data, text='Pausa', variable=v_state, value='P')
r_p.grid(row=0, column=4, padx=6, pady=6, sticky='w')
r_r = tk.Radiobutton(pn_data, text='Riavviata', variable=v_state, value='R')
r_r.grid(row=0, column=5, padx=6, pady=6, sticky='w')
r_c = tk.Radiobutton(pn_data, text='Chiusa', variable=v_state, value='C')
r_c.grid(row=0, column=6, padx=6, pady=6, sticky='w')
e_date = tk.Entry(pn_data, width=22)
e_date.grid(row=0, column=7, padx=6, pady=6, sticky='w')
lbl = tk.Label(pn_data, text='Meccanico :')
lbl.grid(row=0, column=8, padx=6, pady=6, sticky='w')
cmb_mecc = ttk.Combobox(pn_data, state='ReadOnly')
cmb_mecc.grid(row=0, column=9, padx=6, pady=6, sticky='w')
lbl = tk.Label(pn_data, text='Note :')
lbl.grid(row=0, column=10, padx=6, pady=6, sticky='w')
e_note = tk.Entry(pn_data, width=22)
e_note.grid(row=0, column=11, padx=6, pady=6, sticky='ew')
pn_data.grid_columnconfigure(11, weight=1)
pn_cmd = tk.Frame(root)  # pannello per pulsanti comando
pn_cmd.grid(row=3, column=0, columnspan=2, sticky='ew')
bt_data = tk.Button(pn_cmd, text='Carica dati', command=on_data)
bt_data.grid(row=0, column=0, padx=6, pady=6, sticky='ew')
bt_close = tk.Button(pn_cmd, text='Chiudi programma', command=root.destroy)
bt_close.grid(row=0, column=1, padx=6, pady=6, sticky='ew')
pn_cmd.grid_columnconfigure(0, weight=1, uniform='a')
pn_cmd.grid_columnconfigure(1, weight=1, uniform='a')

tbl.bind('<<TreeviewSelect>>', on_select)  # binding cambio di selezione

root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)

root.mainloop()

Prevede il caricamento dati tramite la pressione del pulsante "Carica dati" (non è bene mischiare logica di visualizzazione con logica dati) ed una volta che i dati saranno caricati il cambio di selezione invocherà la funzione di callback "on_select" che provvederà ad invocare l'item di riga selezionato ed a operare sui dati.
L'item selezionato è un dizionario
============ RESTART: /home/nuzzopippo/src/posts/ibooms/esempio_01.py ===========
{'text': '', 'image': '', 'values': [654, 'Mirko', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', 'C', '', ''], 'open': 0, 'tags': ''}

vi è un print commentato nella funzione, inserito per mostrarTi cosa stai trattando, del dizionario interessano i dati della chiave "values" che vengono letti ed interpretare per decidere quali dati mostrare. In particolare, viene mostrata la sola data associata allo stato della commessa.

Spero Ti sia utile.

.... hai qualche miglioria da consigliarmi a riguardo?
... sig ... da dove comincio?
@iBooma, stai iniziando a studiare python apparentemente digiuno su ben due argomenti complessi (interfacce grafiche e database relazionali), prescindendo dalle cognizioni design applicativo non valutabili, temo Ti aspettino numerosi momenti di frustrazione.
Ti posso solo suggerire di non aver fretta a "produrre" ed acquisire quanto meglio Ti riesce le basi del linguaggio con particolare riferimento alle classi, reputo la programmazione funzionale un patter inadeguato alle GUI, la OOP è quasi obbligata per esse.
Poi, studiati bene i dati che vuoi gestire, se sono le Tue procedure ad aver registrato quei dati devi affinare la logica, non è ammissibile una chiusura antecedente una ripresa (vedi commessa 1111) o una data di inizio non impostata ... non parliamo dei meccanici mancanti ;)

Comunque, per quel che si può si è qua

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Ciao nuzzopippo, ti ringrazio come sempre sei di grande aiuto...

Citazione
se sono le Tue procedure ad aver registrato quei dati devi affinare la logica, non è ammissibile una chiusura antecedente una ripresa (vedi commessa 1111) o una data di inizio non impostata ... non parliamo dei meccanici mancanti ;)
quei dati che vedi sono il frutto di vari errori , quando vedi cose tipo chiusura antecedente una ripresa ho solo per sbaglio selezionato il riavvio prima della pausa, lo stesso vale per i meccanici mancanti, non ho ancora messo i controlli e relativi messaggi di errori per evitare che accada. Se compili tutto correttamente seguendo le giuste cadenze temporali funziona tutto correttamente...

Citazione
@iBooma, stai iniziando a studiare python apparentemente digiuno su ben due argomenti complessi (interfacce grafiche e database relazionali), prescindendo dalle cognizioni design applicativo non valutabili, temo Ti aspettino numerosi momenti di frustrazione.
proprio digiuno no, però devo ancora imparare molto, questo sicuramente si .... mi metto subito a studiare l'esempio che mi hai fornito ci lavoro sopra e ti aggiorno sul risultato, nel frattempo studierò sicuramente anche l'ambiente grafico e i db  .... Grazie per il tempo che mi hai dedicato ...

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
 Ciao @nuzzopippo, mi sono messo a studiare il tuo esempio e ho appresso molte cose, anche a livello logico. Vedere la differenza di costruzione del codice mi ha  veramente aiutato .... Grazie  :)

ho adattato la tua on select al mio "mappazone"  e FUNZIONA , ad ogni selezione cambia la commessa , il nominativo del meccanico e le info , mi manca di far aggiornare i radiobotton dello stato ma sono già soddisfatto del risultato...

def on_select(evt):  # espone i dati selezionati nella treeview nei relativi widget
   
    data = tabella.item(tabella.focus())['values']
    if not data: return
    commessa_entry.delete(0, tk.END)
    commessa_entry.insert(tk.END, str(data[0]))
    nominativo_combobox.set(data[1])
    informazioni_entry.delete(0, tk.END)
    informazioni_entry.insert(tk.END, data[8])   



tabella.bind('<<TreeviewSelect>>', on_select)  # binding cambio di selezione


Grazie grazie grazie .....
« Ultima modifica: Gennaio 26, 2023, 01:11 da iBooma »