Forum >> Programmazione Python >> GUI >> Problema con lista values[] in programma con GUI

Pagina: 1

Buon giorno, riporto di seguito il codice in cui è dichiarato globalmente

la lista values[] nella quale vengono messe le variazioni di posizione di 10 sladers.

Se modifico gli sladers tali variazioni avvengono pure nei valori di values e stampati nella bash mentre se carico da file le posizioni in esso contenute

tali vari con vengono caricati da files a values[].

Non capisco perchè dato che values[] è globale non carica le posizioni da file.

Scusate l'ignoranza con gli oggetti ma non li padroneggio bene.
import sys
import os
import json
import tkinter as tk

from tkinter import simpledialog
from tkinter import messagebox

values = [0,0,0,0,0,3300,3300,3300,3300,3300,'0']

class ModelSelector(tk.simpledialog.Dialog):
    ''' Dialog per selezionare modelli di suoni. '''
    def __init__(self, parent, cache):
        self.cache = cache
        self.model = None
        super().__init__(parent, title='Scelta modello')

    def body(self, frame):
        self.frame = frame
        self.lst = tk.Listbox(frame)
        self.lst.grid(row=0, column=0, padx=(5,1), pady=5, sticky='nsew')
        vscrol = tk.Scrollbar(frame, orient=tk.VERTICAL,
                              command=self.lst.yview)
        self.lst.configure(yscrollcommand=vscrol.set)
        vscrol.grid(row=0, column=1, padx=(1,5), pady=5, sticky='ns')

        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)
        self._load_models()
        return frame

    def buttonbox(self):
        pn_cmd = tk.Frame(self.frame)
        pn_cmd.grid(row=1, column=0, columnspan=2, sticky='ew')
        bt_ok = tk.Button(pn_cmd, text='Ok', command=self._on_ok)
        bt_ok.grid(row=0, column=0, padx=5, pady=5, sticky='ew')
        bt_cancel = tk.Button(pn_cmd, text='Annulla', command=self._on_cancel)
        bt_cancel.grid(row=0, column=1, padx=5, pady=5, sticky='ew')
        pn_cmd.grid_columnconfigure(0, weight=1, uniform='bt')
        pn_cmd.grid_columnconfigure(1, weight=1, uniform='bt')
        

    def _on_ok(self):
        sel = self.lst.curselection()
        if not sel: return
        idx = sel0
        value = self.lst.get(idx)
        if value:
            self.model = value
            self.destroy()

    def _on_cancel(self):
        self.destroy()

    def _load_models(self):
        contents = os.listdir(self.cache)
        models = [x.split('.')0 for x in contents if x.endswith('.json')]
        for m in models:
            self.lst.insert(tk.END, m)

def select_model(app, cache):
    dialog = ModelSelector(app, cache)
    return dialog.model
    

class MainWin(tk.Tk):
    freqs = ['1','2','3','4','5']
    mixer = ['1','2','3','4','5']
    shape = ['1','2','3','4','5']
    def __init__(self):
        super().__init__()
        self._cache = ''
        self._model = ''
        self._set_environment()
        self._make_menus()
        self.populate()

    def _set_environment(self):
        ''' Stabilisce la posizione di storage dei modelli di combinazioni. '''
        # stabilisce la locazione per la cache in una sub-directory
        # della cartella contenente lo script denominata "Modelli"
        app_dir = os.path.abspath(os.path.dirname(sys.argv0))
        self._cache = os.path.join(app_dir, 'Modelli')
        # se la sub-directory non esiste la crea
        if not os.path.exists(self._cache) and not os.path.isdir(self._cache):
            os.mkdir(self._cache)
        
    def _make_menus(self):
        ''' Costruisce un sistema di menu per la finestra. '''        
        menubar = tk.Menu(self, bg='black', fg='white',
                          activebackground='blue', activeforeground='white')
        filemenu = tk.Menu(menubar, bg='black', fg='white',
                          activebackground='blue', activeforeground='white')
        filemenu.add_command(label="New", command=self._on_initialize)
        filemenu.add_separator()
        filemenu.add_command(label="Open", command=self._on_open)
        filemenu.add_separator()
        filemenu.add_command(label="Save", command=self._on_save)
        filemenu.add_command(label="Save As ...",  command=self._on_save_as)
        filemenu.add_separator()
        filemenu.add_command(label="Close", command=self.destroy)
        menubar.add_cascade(label="File", menu=filemenu)
        self.config(menu=menubar)
        
    def populate(self):
        self.title(' SINTHETIZER')
        self.configure(bg='black')
        self._scales = {'freqs': [],
                        'mixer': [], 
                        'shape': []}
        st_pnl = tk.LabelFrame(self, text='', fg='white', background='black')
        st_pnl.pack(padx=5, pady=5)
        st_pnl.grid(row=0, column=0, sticky='nsew')
        self.v_scales = []
        self.h_scales = []
        #for i in range(len(self.shape)):
         #   lbl = tk.Label(st_pnl, text=self.adsrv, background='black', fg='white', pady=10, padx=10, font=10)
          #  lbl.grid(row=0, column=i, padx=12, pady=50, sticky='ne')
           # sc = tk.Scale(st_pnl, from_=25, to=1, showvalue=True,  length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
            #sc.set(0)
            #sc.bind("<ButtonRelease>", self.aggiorna_adsrv)       #binding  adsrv
            #sc.grid(row=2, column=i, padx=10, pady=10, sticky='ne')
            #st_pnl.grid_columnconfigure(i, weight=1)
            #self._scales['adsrv'].append(sc)
        st_pnl.grid_rowconfigure(1, weight=1)
        fr_pnl = tk.LabelFrame(self, text=' Frequency (Hz)', fg="white", background="black")
        fr_pnl.grid(row=0, column=1, sticky='nsew')
        for i in range(len(self.freqs)):
            #lbl = tk.Label(fr_pnl, text=self.freqs, fg='white', background="black")
            #lbl.grid(row=0, column=i, padx=5, pady=50, sticky='ne')
            sc = tk.Scale(fr_pnl, from_=1500, to=0, showvalue=True, length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
            sc.set(0)
            sc.bind("<ButtonRelease>", self.aggiorna_freq)       #binding  freq
            sc.grid(row=2, column=i, padx=10, pady=10, sticky='se')
            self._scales['freqs'].append(sc)
            fr_pnl.grid_columnconfigure(i, weight=1, uniform='fsc')
        fr_pnl.grid_rowconfigure(1, weight=1)
        #fr = tk.LabelFrame(self, text='LFO1 for FM (Hz)', fg="white", background="black")
        #fr.grid(row=1, column=0, sticky='se')
        #for i in range(len(self.lfo1)):
         #   sc= tk.Scale(fr, from_=50, to=0, showvalue=True, length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
          #  sc.set(0)
           # sc.bind("<ButtonRelease>", self.aggiorna_lfo1)       #binding lfo1
            #sc.grid(row=0, column=0, padx=10, pady=10, sticky='se')
            #self._scales['lfo1'].append(sc)
        fr_pnl = tk.LabelFrame(self, text=' Mixer (ohms)', fg="white", background="black")
        fr_pnl.grid(row=1, column=1, sticky='ew')
        for i in range(len(self.mixer)):
            lbl = tk.Label(fr_pnl, text=self.mixer, fg="white", background="black")
            lbl.grid(row=1, column=i, padx=10, pady=10, sticky='se')
            sc = tk.Scale(fr_pnl, from_=100000, to=0, showvalue=True, length=200, tickinterval=1,background='black', fg='white', orient=tk.VERTICAL)
            sc.set(0)
            sc.bind("<ButtonRelease>", self.aggiorna_mixer)       #binding mixer
            sc.grid(row=1, column=i, padx=10, pady=10, sticky='se')
            self._scales['mixer'].append(sc)   

        self.grid_columnconfigure(0, weight=1)

    def _on_initialize(self):
        ''' Imposta lo stato iniziale per un nuovo modello di frequenze. '''
        self._model = ''
        for s in self._scales['freqs']:
            s.set(0)
        for s in self._scales['mixer']:
            s.set(0)

    def _on_save(self):
        if not self._model:
            name = simpledialog.askstring('Nome modello', 'inserire il nome da assegnare', parent=self)
            if not name:
                return
            self._model = os.path.join(self._cache, name + '.json')
        if os.path.exists(self._model):
            msg = 'Nome modello già in uso'
            messagebox.showerror('Duplicazione', msg, parent=self)
            return
        values = {}
        for k in self._scales.keys():
            sets = []
            for i in range(len(self._scalesk)):
                sets.append(self._scalesk.get())
            valuesk = sets
        try:
            with open(self._model, 'w') as f:
                json.dump(values, f)
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return

    def _on_save_as(self):
        if not self._model:
            msg = 'Questo modello non ha nome, utilizzare il comando "save"'
            messagebox.showinfo('Comando improprio', msg, parent=self)
            return
        name = simpledialog.askstring('Nome modello', 'inserire il nome da assegnare', parent=self)
        if not name:
            return
        name = os.path.join(self._cache, name + '.json')
        if os.path.exists(name):
            msg = 'Nome modello già in uso'
            messagebox.showerror('Duplicazione', msg, parent=self)
            return
        self._model = name
        values = {}
        for k in self._scales.keys():
            sets = []
            for i in range(len(self._scalesk)):
                sets.append(self._scalesk.get())
            valuesk = sets
        try:
            with open(self._model, 'w') as f:
                json.dump(values, f)
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return        

    def _on_open(self):
        model = select_model(self, self._cache)
        if not model: return
        self._model = os.path.join(self._cache, model + '.json')
        try:
            with open(self._model) as f:
                values = json.load(f)    
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return
        for k in self._scales.keys():
            data = valuesk   #data è il dizionario degli slader
            print(valuesk)
            for i in range(len(self._scalesk)):
                self._scalesk.set(data)
                
    
    def aggiorna_freq(self, evt):
        w = evt.widget
        try:
            index= self._scales['freqs'].index(w)
            valuesindex = w.get()
            for index in range(0,5):
                print(index, '=>', valuesindex)
        except ValueError as e:
            return                        

    def aggiorna_mixer(self, evt):
        w = evt.widget
        try:
            index = self._scales['mixer'].index(w)
            values[index + 5] = w.get()
            for index in range(5,10):
                print(index, '=>', valuesindex)
        except ValueError as e:
            return           

if __name__ == '__main__':
    #crea finestra
    app = MainWin()
    app.configure(background='black')
    app.geometry("1000x1000+0+0")
    app.resizable(False,False)
    app.configure(background="black")
    app.mainloop()


   

    



Nessuno mi può aiutare?






Ecco l'allegato:



Allegati
Ciao @Fabio75 ... sempre mixer eh? :D




Ho sommariamente testato il file da Te allegato nel 2° post, evidentemente manipolato rispetto al primo, ed a parte il doppio lancio della applicazione

if __name__ == '__main__':
    #crea finestra
    app = MainWin()
    app1 = MainWin()
    app.configure(background='black')
    app.geometry("1000x1000+0+0")
    app.resizable(False,False)
    app.configure(background="black")
    app.mainloop()
    app1.populate()
Che Ti darà errore per il "popolamento" di app1 DOPO l'avvio del mainloop (elimina app1, non serve)




Sembra caricare correttamente i dati del mixer salvati (ovviamente nello oggetto "app") ... senza studiarmi attentamente il codice da Te proposto, vorresti aggiornare sulle problematiche che trovi nel file allegato nel secondo post?




Per altro, se posso suggerire, trovo che l'utilizzo di variabili globali a livello di modulo sia un brutto modo di procedere, una classe "dovrebbe" quanto più possibile essere indipendente da fattori esterni, penso sia più opportuno utilizzare variabili di istanza per i dati da gestire e/o parametri nei metodi nel passaggio dati tra un oggetto e l'altro.




Fai sapere :)
Fatti non foste a viver come bruti...
Ho aggiunto altre due righe di oggetti slader e mi succede che se carico con File | open prova1 il modello non viene caricato su values e gli sladers.

Poi ci sono probabili errori negli indici degli array di "for index in range():"

nei metodi di aggiornamento, poi mi da errore quando clicco su freq SIDEA e mixer SIDEB mi da errore:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/media/fabio/6CA2E3C5A2E3923E/Progetti con eagle/SINTHETIZER/SOFTWARE/PC/prova.py", line 267, in aggiorna_mixer
    index = self._scales['mixera'].index(w)
KeyError: 'mixera'
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/media/fabio/6CA2E3C5A2E3923E/Progetti con eagle/SINTHETIZER/SOFTWARE/PC/prova.py", line 257, in aggiorna_freq
    index= self._scales['freqsa'].index(w)
KeyError: 'freqsa'


Ecco la copia degli errori.
Allegati
Ho corretto gli indici e mi rimangono i due errori sui metodi di aggiornamento di values[].





--- Ultima modifica di fabio75 in data 2025-10-19 13:54:04 ---
Allegati


Pagina: 1



Esegui il login per scrivere una risposta.