Visualizza post

Questa sezione ti permette di visualizzare tutti i post inviati da questo utente. N.B: puoi vedere solo i post relativi alle aree dove hai l'accesso.


Post - nuzzopippo

Pagine: [1] 2 3 4
1
Base / Re:Libri per imparare Python
« il: Maggio 05, 2019, 13:04 »
Ciao :)

Iniziando a mia volta, questo libro l'ho trovato buono, tant'è che ho intenzione di rileggerlo.

Ti suggerirei di dare una guardata nella sezione "Documentazione" ed anche nelle altre sezioni, vi sono post in merito e materiale indicato per vari aspetti.

2
I miei saluti a Voi.

Cercando di realizzare un "controllo" personalizzato (assemblando vari widget) ho provato, tra l'altro, una "composizione" che prevede l'utilizzo di una scrollbar non associata alla view di un secondo widget.
L'utilizzo della scrollbar è relazionato al solo scorrimento di un indice di lista dati.

La prova, tutto sommato, ha avuto successo, almeno in linea di massima, in questo modo :
dichiarazione nello __init_della classe :
        self.pivot_scroll = tk.Scrollbar(self,
                                         orient=tk.VERTICAL,
                                         jump=1,
                                         command=self._scrollEvent)

l'opzione "jump=1" è data per limitare gli eventi al solo rilascio del tasto del mouse

definizione del "set" per la scrollbar al caricamento dei dati :
    def set_data(self, dati):
        self.dati = dati
        self.pivot = 0
        for riga in self.rows:
            riga.clear()
        # configurazione scrollbarr
        self.pivot_scroll.set(0, len(self.dati) - self.righe)
        # fine per scroll
        self._refresh_rows()

ove viene impostato, per la scrollbar, un "intervallo" pari alla consistenza dei dati decurtata degli elementi visualizzati, tale impostazione è necessaria, in assenza si hanno "out of range" ad ogni evento proveniente dalla scrollbar

gestito valutando i dati passati dalla scrollbar al gestore (handler, se volete) associato
    def _scrollEvent(self, *L):
        """Gestisce lo scroll della vertical barr associata."""
        if not self.dati: return
        for elem in L: print(elem, end=' - ')
        print()
        op, valore = L[0], L[1]
        if op == 'scroll':
            modo = L[2]
            if modo == 'pages':
                val = int(valore) * self.righe
            else:
                val = int(valore)
            if (self.pivot + val) < 0:
                self.pivot = 0
            elif (self.pivot + val) > (len(self.dati) - self.righe):
                self.pivot = len(self.dati) - self.righe
            else:
                self.pivot += val
        elif op == 'moveto':
            self.pivot += int(len(self.dati) * float(valore)) - 1
            if self.pivot < 0:
                self.pivot = 0
            elif self.pivot > len(self.dati) - self.righe:
                self.pivot = len(self.dati) - self.righe
        self._refresh_rows()


Come detto, le impostazioni sopra per funzionare funzionano ma in modo insoddisfacente : lo slider della scrollbar assume la dimensione dell'intera area disponibile, cosa non sorprendente, e (questo è strano) si "ridimensiona" in caso di trascinamento a partire dai bordi estremi dello stesso, tale ridimensionamento permate e da quel momento è possibile "agganciare" e trascinare lo slider, la "precisione" lascia a desiderare ed il posizionamento effettivo dello slider è insussistente.
Se occorressero maggiori dettagli od una visualizzazione grafica della circostanza potete vedere qui, sono semplici appunti di apprendimento.

Non so se è possibile farlo ma vorrei realizzare un controllo adeguato della rappresentazione dei dati visualizzati in rapporto all'insieme degli stessi, il tutto completamente avulso da view di elementi grafici.
Ho molto cercato e letto ma ho trovato pochissimo, se non nulla, di specifico in merito ad una definizione  delle specifiche dello slider o, magari, ci sono incappato e non ho compreso, data la mia ignoranza dell'inglese.

Qualcuno di Voi avrebbe indicazioni e/o suggerimenti in merito?

Grazie dell'attenzione  :caffè:

3
Base / Re:Storage parametri applicazione : un consiglio
« il: Aprile 23, 2019, 18:21 »
Grazie delle info @RicPol

Leggersi il s.o., quindi, poi regolarsi.

...Poi per fare questo sarebbe buona educazione fornire anche un installer/uninstaller che pulisce correttamente i vari pezzetti lasciati in giro...
Se però si trattta del solito programmino distribuito alla selvaggia, allora è di gran lunga preferibile usare una sub-directory "interna" ...
beh, la parte evidenziata rientra tra le "intenzioni" in divenire, anche se argomento che temo metterà a dura prova le mie denutrite meningi, allo stato men che selvagge.
La sub interna alla directory applicativa l'avevo considerata ma in genere non la uso per abitudine, più che altro perché le piccole applicazioni che faccio a mio uso e consumo le porto in giro su chiavetta e le faccio girare su diversi computer, tutti linux ma con caratteristiche differenti, alla lunga ho una preferenza per lo storage sulla macchina in uso ... anche se come motivo non è per nulla buono :)

Grazie, ciao

4
Base / Re:Storage parametri applicazione : un consiglio
« il: Aprile 22, 2019, 07:40 »
Vi ringrazio delle risposte.

Per lo meno, ho conferma che detto metodo è applicabile nei s.o. più diffusi, anche se "nascondere" lascia il tempo che trova.

Interessante la proposta di standard segnalata da @bebo, sarebbe ora che si adottassero schemi di comportamento unificati, per limitare la confusione nelle home-dir ... già ci pensa l'utente a crearla :)
da una veloce verifica nel mio Ubuntu 18.04, sembrerebbe parzialmente adottata solo da unity per sue specifiche esigenze, da verificare circa i permessi in scrittura

NzP:~$ echo "$XDG_DATA_HOME"

NzP:~$ echo "$XDG_CONFIG_HOME"

NzP:~$ echo "$XDG_CONFIG_DIRS"
/etc/xdg/xdg-unity:/etc/xdg
NzP:~$ echo "$XDG_CACHE_HOME"

NzP:~$ echo "$XDG_RUNTIME_DIR"
/run/user/1000
NzP:~$ ls "$XDG_RUNTIME_DIR"
bus     dconf  gnupg  gvfs-burn  pulse    unity
dbus-1  gdm    gvfs   keyring    systemd  update-notifier.pid
NzP:~$

Comunque, faccenda da tener d'occhio

5
Base / Storage parametri applicazione : un consiglio
« il: Aprile 20, 2019, 12:43 »
Buon giorno a Voi ... e buona Pasqua, data la prossimità :)

Desidererei un consiglio :
nei sistemi unix-like è ampiamente usato memorizzare parametri opzionali di una applicazione scelti da un utente in una direttrice nascosta nella home dell'utente, cosa semplice da realizzare con python

import os
...
def load_app_configurations():
    '''Acquisisce, se esistono, le scelte applicative salvate.'''
    home = os.path.expanduser('~')
    app_dir = os.path.join(home, '.app_name')
    if not os.path.exists(app_dir):
        os.mkdir(app_dir)

mi apprestavo ad utilizzare una tale metodologia ma mi son fermato un attimo, so che "funzionerebbe" anche in windows, almeno per alcune versioni, ma mi chiedo se esiste una qualche convenzione/linea guida in merito, almeno per l'ambito python ...  sapreste darmi suggerimenti in merito?

6
Tkinter / Re:layout "grid", classi e persistenza oggetti
« il: Aprile 16, 2019, 06:23 »
Risolto, il problema era nella notazione "unica" utilizzata per definire il widget e la sua posizione nella griglia : non da errore ma non restituisce l'oggetto creato. Bisogna, quindi, tener separate le definizioni ed i posizionamenti.

Mi hanno "fregato" la mancanza di eccezioni e "vecchie" esperienze.

Per improbabili interessati :

Notazione accettata ma inutilizzabile :

        self.lbl_dida = tk.Label(self,
                                text='...',
                                justify='left',
                                ).grid(row=0, column=1, sticky='nsew')


Notazione funzionale :

        self.lbl_dida = tk.Label(self,
                                text='...',
                                justify='left',
                                )
...
        self.lbl_dida.grid(row=0, column=1, sticky='nsew')


Mi si perdoni se Vi ho fatto perdere tempo a leggere.

7
Tkinter / [Risolto] layout "grid", classi e persistenza oggetti
« il: Aprile 15, 2019, 09:19 »
I miei saluti a Voi :)

Intrigato da una idea reperita altrove, mi sono avventurato a costruire una specie di "controllo" composito con tkinter che provvede ad esporre righe di immagini miniaturizzate e didascalie. Nel costruirlo mi sono anche scritto una serie di test per verificare la "resa" di quanto fatto in vali punti di sviluppo.

Ho implementato una versione utilizzante il metodo "pack()" costituita da due classi, una definente una singola "riga" dati (immagine/didascalia) mentre la seconda visualizza un insieme di tali righe e fornisce i metodi per la navigazione tra i dati. Tale versione è funzionante.

Insoddisfatto da alcune questioni di resa grafica degli automatismi di pack() ho provato a definire una variante dell'oggetto utilizzante il metodo "grid()" ed incappando già alla definizione della singola riga in una serie di problematiche che, dopo un po' di ricerche e prove, credo si individuino in una mancata persistenza degli oggetti invocati dal codice per una qualche peculiarità del metodo grid() che non mi riesce di individuare, probabilmente per la mia ignoranza dell'inglese (enorme palla al mio piede)

Appresso, esemplifico il codice, funzionante, del costruttore di una riga, versione utilizzante pack(), e della sua invocazione, con inseriti del print di debug.

costruttore :

class FRMTumbnail(tk.Frame):
    '''Pannello per singola miniatura (tumbnail) con descrizione.'''
    def __init__(self, master, mater, imgdim=60):
        self.mater = mater
        self.f_img = ''
        super().__init__(master)
        self.dim_tmb = imgdim
        self._curr_img = None
        self.indice = None
        self.default_bc = self.cget('bg')
        self.configure(relief='sunken', border=2, padx=2, pady=2)
        self.cnv_tmb = tk.Canvas(self,
                                 width=self.dim_tmb,
                                 height=self.dim_tmb,
                                 bg='#ffffc0',
                                 relief='raised',
                                 border=2
                              )
        self.cnv_tmb.pack(side='left')
        print('self.cnv_tmb è : ', self.cnv_tmb)
        print(self.cnv_tmb)
        self.cnv_tmb.bind('<Button-1>', self._scelto)
        f = tk.Frame(self, height=self.dim_tmb+4)
        f.pack(side='left', expand=True, fill='x')
        #f.pack_propagate(0)
        self.lbl_dida = tk.Label(f,
                                text='..'*10,
                                justify='left',
                                )
        self.lbl_dida.pack(expand=True, fill='both')
        print('self.lbl_dida è : ', self.lbl_dida)
        self.lbl_dida.bind('<Button-1>', self._scelto)


invocazione:

class GUI_01(tk.Tk):
    ''' Finestra principale test 01 : singola riga. '''

    def __init__(self, fnome='', dim=60):
        super().__init__()
        self.f_nome = fnome
        self.title('Test 01')
        sfondo = tk.Frame()
        sfondo.pack(fill='both')
        self.f = fd.FRMTumbnail(sfondo, None, dim)
        self.f.pack(fill='x')
        print('self.f è : ', self.f)
        f2 = tk.Frame(sfondo, relief='sunken', padx=2, pady=2)
        f2.pack(fill='x')
        btn = tk.Button(f2, text='Mostra immagine', command=self.mostra)
        btn.pack()
        self.minsize(300, self.winfo_reqheight())
        # self.update()
        centraFinestra(self)
   
    def mostra(self):
        self.f.set_fileimg(self.f_nome)
        self.f.set_dida("un po' di testo a caso")


Ed ora analoghi costruttore ed invocazione con grid(), si noti il commento dei "bind()", con ciò la riga viene visualizzata correttamente ma è inutilizzabile.

Costruttore:

class GriFRMTmb(tk.Frame):
    '''Pannello per singola miniatura (tumbnail) con descrizione.'''
    def __init__(self, master, mater, imgdim=60):
        self.mater = mater
        self.f_img = ''
        super().__init__(master)
        self.dim_tmb = imgdim
        self._curr_img = None
        self.indice = None
        self.default_bc = self.cget('bg')
        self.configure(relief='sunken', border=2, padx=2, pady=2)
        self.cnv_tmb = tk.Canvas(self,
                                 width=self.dim_tmb,
                                 height=self.dim_tmb,
                                 bg='#ffffc0',
                                 relief='raised',
                                 border=2
                                 ).grid(row=0, column=0, sticky='w')
        print('self.cnv_tmb è : ', self.cnv_tmb)
        #self.cnv_tmb.bind('<Button-1>', self._scelto)
        self.lbl_dida = tk.Label(self,
                                text='...',
                                justify='left',
                                ).grid(row=0, column=1, sticky='nsew')
        #self.lbl_dida.bind('<Button-1>', self._scelto)
        print('self.lbl_dida è : ', self.lbl_dida)
        self.columnconfigure(1, weight=1)


invocazione:

class GUI_01_G(tk.Tk):
    ''' Finestra principale test 01 - variante layout grid : singola riga. '''

    def __init__(self, fnome='', dim=60):
        super().__init__()
        self.f_nome = fnome
        self.title('Test 01-Grid')
        sfondo = tk.Frame().grid(sticky='nsew')
        self.f = fd.GriFRMTmb(sfondo, None, dim).grid(row=0,
                                                        padx=2,
                                                        pady=2,
                                                        sticky='ew'
                                                        )
        print('self.f è : ', self.f)
        btn = tk.Button(sfondo,
                        text='Mostra immagine',
                        command=self.mostra).grid(row=1,
                                                  padx=2,
                                                  pady=2,
                                                  sticky='nsew'
                                                  )
        self.columnconfigure(0, minsize=300, weight=1)
        self.update()
        centraFinestra(self)
   
    def mostra(self):
        self.f.set_fileimg(self.f_nome)
        self.f.set_dida("un po' di testo a caso")

(mi si perdoni l'incompleta aderenza alla Pep8)

e qui segue l'output del test effettuato per le due versioni :

NzP:~$ python3 test.py 1 risorse/01.jpg 60
self.cnv_tmb è :  .!frame.!frmtumbnail.!canvas
.!frame.!frmtumbnail.!canvas
self.lbl_dida è :  .!frame.!frmtumbnail.!frame.!label
self.f è :  .!frame.!frmtumbnail
NzP:~$ python3 test.py 5 risorse/01.jpg 60
self.cnv_tmb è :  None
self.lbl_dida è :  None
self.f è :  None
NzP:~$


Mi sembra evidente che con l'utilizzo di pack() le variabili di istanza nelle classi vengono correttamente create mentre utilizzando grid() invece no
 ... malgrado abbia cercato nella docs ed in rete mi son fermato qui, non mi riesce di capirne il perché e come rimediare, qualcuno di Voi conosce il problema e può darmi indicazioni in merito?

Scusate la lunghezza del post, non mi riuscirebbe di essere chiaro, altrimenti.

8
Base / Re:ottenere indirizzocompleto da zipcode
« il: Marzo 28, 2019, 20:11 »
Se con zipcode intendi il "CAP" italiano, non vai tanto liscio neanche limitando ai soli codici nazionali, essendo non univoci e, in diversi casi, anche multipli.

Esempio scaricando la lista dei comuni dal sito comuni-italiani.it, trovi si univocamente il tuo codice

>>> with open('listacomuni.csv', 'r', encoding='ISO-8859-2') as f:
lista = f.read().splitlines()
>>> for riga in lista:
elem = riga.split(';')
if elem[5] == '28822':
print(elem[1])

Cannobio
>>>


Però ci trovi più comuni già testando i primi in elenco:

>>> for riga in lista:
elem = riga.split(';')
if elem[5] == '26834':
print(elem[1])

Abbadia Cerreto
Corte Palasio

Ho verificato cap corrispondenti a più di una decina di comuni, e molti capoluoghi e città metropolitane hanno range di CAP assegnati ... problema di difficile soluzione il tuo, temo, non essendoci univocità di sorta.

Se hai dati ulteriori disponibili, vi sarebbero gli elenchi istat, più articolati.

9
Tkinter / Re:problema con menu tkinter
« il: Marzo 23, 2019, 10:37 »
sono un novizio di python ....
...
ma non funziona, inoltre come faccio se devo anche avere un return dalla funzione ?

Ciao @bot, mi perdonerai se rispondo più per fare esercizio che per dare una risposta esaustiva, la programmazione di interfacce grafiche è complessa e mi ci sono ancora avventurato poco.

Complessa è anche la risposta in merito all'argomento che poni, dipendendo in notevole misura dal design progettuale della applicazione, mio parere (gli esperti correggano) è che di per se le funzioni di callback dovrebbero limitarsi a gestire gli eventi, delegando al corpo delle funzioni di ottenere ciò che occorre ed eseguire le azioni opportune.
È opportuno, posto il "problema" progettare il proprio codice e le proprie classi in modo idoneo ad ottenere il risultato voluto tenendo presente che in sede di inizializzazione (ed anche dopo, spesso) non è che conoscano i valori dei parametri che Tu vorresti passare ... Ti ho preparato un esempio in tal senso partendo da codice recentemente postato in questo post, l'idea è semplicemente di ottenere che al comando di menu "Cerca Libro" una funzione si occupi di interrogare uno specifico oggetto per ottenere i dati inseriti nei controlli e li stampi.
Se copi il codice e lo modifichi come sotto indicato:
RIGA 71
        menu_libri.add_command(label='Cerca libro', command=self._cerca_libro)


CLASSE FinestraPrincipale - aggiugere metodo

    def _cerca_libro(self):
        if isinstance(self.sfondo, FrmLibro):
            valori = self.sfondo.dai_valori()
            print(valori)
        else:
            print('Nessun pannello libri presente')


CLASSE FrmLibro - aggiungere metodo

    def dai_valori(self):
        valori = {'autore': self.autore.get(),
                  'titolo': self.titolo.get()
                  }
        return valori

vedrai che lo farà SE starai utilizzando un pannello di classe "FrmLibro".
Sotto un output senza e con utilizzo di tale pannello (Frame, per meglio dire)
>>> %Run con_classi.py
Nessun pannello libri presente
{'autore': 'Nicola Aloia - Fausto Rabitti', 'titolo': 'SQL Sintassi e utilizzo'}


Andiamo ora ad una parte specifica del Tuo post, ossia : come inserire un parametro "variabile" nella definizione del command di un menu?

Risposta non semplice al mio (basso) livello di conoscenza (gli esperti potranno, bontà loro, integrare) , la prima domanda da porsi è : come fa l'istanza di menu a conoscere il parametro da utilizzare, , come si ottiene tale parametro?
Alla sua definizione, la funzione di callback potrà al più conoscere le variabili di classe ed istanza della classe in cui viene definita, potrà leggerli direttamente e/o  ottenerli se tali variabili sono "oggetti" grafici (widgets) riportando il discorso all'esempio prima esposto.

Comunque, diciamo che voglia "per forza" passare un "parametro" ad una funzione di callback invocata alla selezione di una voce di menu, non potrai farlo direttamente, provaci, una definizione con parametro alla definizione di un command di menu viene eseguito alla sola inizializzazione (mi si corregga se sbaglio), ma puoi ricorrere ad uno "sporco trucco" e definire una funzione lambda da richiamare al "command=...", a patto che tale "parametro" sia un oggetto conoscibile (una entry, una istanza StringVar, etc...), ciò riporta sempre alla considerazione iniziale ma voglio proporti n esempio funzionante in tal senso, è una variante all'esempio precedente (compattato ai soli "libri") che legge e richiama una funzione esterna alla classe di ricerca, in una lista di tuple, una stringa inserita nel titolo.
Il codice :

# -*- coding: utf-8 -*-

import tkinter as tk
import tkinter.messagebox as tm

libri = [('SQL Sintassi ed utilizzo', 'Nicola Aloia - Fausto Rabitti'),
         ('Core Java 2 volume 1 - Fondamenti', 'Cay S. Horstmann - Gary Cornell'),
         ('Core Java 2 volume 2 - Tecniche avanzate', 'Cay S. Horstmann - Gary Cornell'),
         ('La svastica sul sole', 'Philip K. Dick'),
         ('Universo Orbitsville', 'Bob Shaw'),
         ('scienza e coscienza', 'A.C. Bhaktivedanta Swami Pabhupada')
         ]


# *** CLASSI DELLE FINESTRE ***

class LoginFrame(tk.Toplevel):
   
    def __init__(self, master=None):
        self.master = master
        super().__init__(self.master)
        self.label_nome_utente = tk.Label(self, text="Nome Utente")
        self.label_password = tk.Label(self, text="Password")
        self.entry_nome_utente = tk.Entry(self)
        self.entry_password = tk.Entry(self, show="*")
        self.label_nome_utente.grid(row=0, sticky=tk.E)
        self.label_password.grid(row=1, sticky=tk.E)
        self.entry_nome_utente.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)
        self.logbtn = tk.Button(self, text="Login", command=self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)
        self.update()
        centra_finestra(self)
       
    def _login_btn_clicked(self):
        nome_utente = self.entry_nome_utente.get()
        password = self.entry_password.get()

        if nome_utente == "marco" and password == "password":
            self.destroy()
            self.master.mostra()
        else:
            self.master.chiudi()


class FinestraPrincipale(tk.Tk):
   
    def __init__(self):
        super().__init__()
        # configurazione
        self.title('pyLibri 0.1')
        self.geometry('960x640')
       
        f = tk.Frame(self)
        f.pack(expand=True, fill='both')
        subf1 = tk.Frame(f, padx=5, pady=5)
        subf1.pack(expand=True, fill='x', padx=5, pady=5)
        lbl1 = tk.Label(subf1, text='Titolo :', width=7, justify='left')
        lbl1.pack(side='left', anchor='n')
        self.titolo = tk.Entry(subf1, width=15)
        self.titolo.pack(side='left', expand=True, fill='x', anchor='n')
        subf2 = tk.Frame(f, padx=5, pady=5)
        subf2.pack(expand=True, fill='x', padx=5, pady=5)
        lbl2 = tk.Label(subf2, text='Autore :', width=7, justify='left')
        lbl2.pack(side='left', anchor='n', padx=5, pady=5)
        self.autore = tk.Entry(subf2, width=15)
        self.autore.pack(side='left', expand=True, fill='x', anchor='n', padx=5, pady=5)
       
        barra_menu = tk.Menu(self)
        self.config(menu=barra_menu)
        menu_libri = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Libri', menu=menu_libri)
        menu_libri.add_command(label='Nuovo libro')
        x = lambda: self._cerca_libro(self.titolo.get())
        menu_libri.add_command(label='Cerca libro', command=x)
        menu_libri.add_command(label='Cancella libro')
        menu_uscita = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Uscita', menu=menu_uscita)
        menu_uscita.add_command(label='Esci', command=self.destroy)
        self.sfondo = tk.Frame(self, padx=0, pady=0)
        self.sfondo.pack(expand=True, fill='both', padx=0, pady=0)
        self.nascondi()
        LoginFrame(self)
       
    def nascondi(self):
        ''' Nasconde la finestra.'''
        self.withdraw()

    def mostra(self):
        ''' Mostra la finestra '''
        self.deiconify()
        centra_finestra(self)
   
    def chiudi(self):
        ''' Chiude la finestra.'''
        tm.showerror("Errore", "Nome utente o password errata")
        self.destroy()
   
    def _cerca_libro(self, titolo):
        if titolo:
            print('Cerco libri con', titolo, 'nel titolo')
            risult = cerca_titolo(titolo)
            if risult:
                for libro in risult:
                    print(libro)
            else:
                print('Nessun elemento trovato')
        else:
            print('Nessun titolo inserito')
       

# *** FUNZIONI GLOBALI ****

def centra_finestra(gui):
    ''' Centra una finestra, passata come parametro, sullo schermo '''
    l = gui.winfo_screenwidth()
    a = gui.winfo_screenheight()
    wx = gui.winfo_width()
    wy = gui.winfo_height()
    gui.geometry('{}x{}+{}+{}'.format(wx, wy, (l-wx)//2, (a-wy)//2))


def cerca_titolo(titolo):
    ''' Simula una ricerca in una lista di titoli'''
    risult = []
    for libro in libri:
        if libro[0].lower().find(titolo.lower()) != -1:
            risult.append(libro)
    return risult


# *** START APPLICAZIONE ***

if __name__ == '__main__':
    app = FinestraPrincipale()
    app.mainloop()


Personalmente, non conosco o immagino metodi per ottenere un valore di ritorno alla selezione di una voce di menu.
La selezione di una voce di menu è e rimane, un evento, suo compito è scatenare azioni non restituire "risultati", sono le azioni avviate a dover produrre risultati.

Spero che ciò che credo (si correggano i miei eventuali abbagli) di aver capito ed ho cercato di esporre Ti sia utile.

10
Tkinter / Re:Tkinter e menu
« il: Marzo 13, 2019, 19:59 »

Ciao @ElTriestin, benvenuto.

È un paio di giorni  che guardo questo post, aspettando gli utenti esperti, per imparare dalla Loro risposta, dato che non si vedono oso proporre io una risposta, pur avendo fatto un solo tentativo di programmare GUI in python e presto convintomi che ho molto da imparare "prima" di ritentare.

Veniamo alla Tua domanda :
Ciao a tutti
...Suppongo di dover creare una funzione che "disegni" campi di testo e label con poi il salvataggio dei valori in una tabella MySQL (il programma già funziona in shell, anche se non mi soddisfa perchè la visualizzazione degli elenchi in shell non è pratica)

Sarà solo una mia opinabile opinione ma non credo proprio sia conveniente l'utilizzo di "funzioni" nella programmazione di interfacce grafiche, ritengo molto più indicato l'utilizzo di classi.
Vedo nel Tuo codice una tendenza alla creazione "dinamica" delle interfacce ... si può fare ma, secondo me, ci si complica la vita, in primo luogo, poi credo anche Ti renda impossibile ciò che vuoi fare : che fine fanno i widget che vorresti sostituire (faccenda implicita nella struttura) e come li trovi per gestirli?
Faccenda complessa questa, costringerebbe a tener traccia di una enormità di controlli (per testi, anagrafiche, prentazioni, etc.) e gestirli, molto meglio pensare a finestre specializzate per i vari aspetti operativi e magari una principale per la visualizzazione dei dati imho.

In ogni caso, trovo "improprio" distruggere Tk e ricrearlo, non sarebbe meglio dedicarlo alla finestra principale e nasconderlo per mostrarlo dopo il login?, quest'ultimo potrebbe essere fatto tramite una finestra Toplevel, p.e.

 ... comunque ho dedicato un'oretta a tirar fuori un esempio funzionante sulla base del Tuo codice eseguire la visualizzazione per un "Nuovo libro" (solo per titolo ed autore) facendo la relativa selezione da menu, preparato un "oggetto" per detta visualizzazione ed una funzione di classe preposta (        _carica_libro) la variante alle istruzioni da Te poste è semplicemente
        menu_libri.add_command(label='Nuovo libro', command=self._carica_libro)

il richiamo della funzione alla definizione del command

C'è un però, bisogna eliminare prima ciò che viene sostituito, guardati la classe "FinestraPrincipale" e l'uso della variabile di istanza "self.sfondo", credo che applicata alle altre "visualizzazioni" dovrebbe funzionare ... anche se personalmente eviterei di utilizzare una tale metodica.

Sotto il codice da me fatto (con le considerazioni di sopra), spero possa esserti utile

# -*- coding: utf-8 -*-

import tkinter as tk
import tkinter.messagebox as tm

# *** CLASSI DEI PANNELLI ***

class FrmLibro(tk.Frame):
    ''' Pannello dei libri.'''
   
    def __init__(self, master, *a, **k):
        super().__init__(master, *a, **k)
        self.master = master
        subf1 = tk.Frame(self, padx=5, pady=5)
        subf1.pack(expand=True, fill='x', padx=5, pady=5)
        lbl1 = tk.Label(subf1, text='Titolo :', width=7, justify='left')
        lbl1.pack(side='left', anchor='n')
        self.titolo = tk.Entry(subf1, width=15)
        self.titolo.pack(side='left', expand=True, fill='x', anchor='n')
        subf2 = tk.Frame(self, padx=5, pady=5)
        subf2.pack(expand=True, fill='x', padx=5, pady=5)
        lbl2 = tk.Label(subf2, text='Autore :', width=7, justify='left')
        lbl2.pack(side='left', anchor='n', padx=5, pady=5)
        self.autore = tk.Entry(subf2, width=15)
        self.autore.pack(side='left', expand=True, fill='x', anchor='n', padx=5, pady=5)
       

# *** CLASSI DELLE FINESTRE ***

class LoginFrame(tk.Toplevel):
   
    def __init__(self, master=None):
        self.master = master
        super().__init__(self.master)
        self.label_nome_utente = tk.Label(self, text="Nome Utente")
        self.label_password = tk.Label(self, text="Password")
        self.entry_nome_utente = tk.Entry(self)
        self.entry_password = tk.Entry(self, show="*")
        self.label_nome_utente.grid(row=0, sticky=tk.E)
        self.label_password.grid(row=1, sticky=tk.E)
        self.entry_nome_utente.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)
        self.logbtn = tk.Button(self, text="Login", command=self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)
        self.update()
        centra_finestra(self)
       
    def _login_btn_clicked(self):
        nome_utente = self.entry_nome_utente.get()
        password = self.entry_password.get()

        if nome_utente == "marco" and password == "password":
            self.destroy()
            self.master.mostra()
        else:
            self.master.chiudi()


class FinestraPrincipale(tk.Tk):
   
    def __init__(self):
        super().__init__()
        # configurazione
        self.title('pyLibri 0.1')
        self.geometry('960x640')
        barra_menu = tk.Menu(self)
        self.config(menu=barra_menu)
        menu_libri = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Libri', menu=menu_libri)
        menu_libri.add_command(label='Nuovo libro', command=self._carica_libro)
        menu_libri.add_command(label='Cerca libro')
        menu_libri.add_command(label='Cancella libro')
        menu_soci = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Soci', menu=menu_soci)
        menu_soci.add_command(label='Nuovo socio')
        menu_soci.add_command(label='Cerca socio')
        menu_soci.add_command(label='Cancella socio')
        menu_prenotazioni = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Prenotazioni', menu=menu_prenotazioni)
        menu_prenotazioni.add_command(label='Nuova prenotazione')
        menu_prenotazioni.add_command(label='Cerca prenotazione')
        menu_prenotazioni.add_command(label='Cancella prenotazione')
        menu_uscita = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Uscita', menu=menu_uscita)
        menu_uscita.add_command(label='Esci', command=self.destroy)
        self.sfondo = tk.Frame(self, padx=0, pady=0)
        self.sfondo.pack(expand=True, fill='both', padx=0, pady=0)
        self.nascondi()
        LoginFrame(self)
       
    def nascondi(self):
        ''' Nasconde la finestra.'''
        self.withdraw()

    def mostra(self):
        ''' Mostra la finestra '''
        self.deiconify()
        centra_finestra(self)
   
    def chiudi(self):
        ''' Chiude la finestra.'''
        tm.showerror("Errore", "Nome utente o password errata")
        self.destroy()
   
    def _carica_libro(self):
        self.sfondo.destroy()
        self.sfondo = FrmLibro(self, padx=0, pady=0)
        self.sfondo.pack(expand=True, fill='both', padx=0, pady=0)
       
       

# *** FUNZIONI GLOBALI ****

def centra_finestra(gui):
    ''' Centra una finestra, passata come parametro, sullo schermo '''
    l = gui.winfo_screenwidth()
    a = gui.winfo_screenheight()
    wx = gui.winfo_width()
    wy = gui.winfo_height()
    gui.geometry('{}x{}+{}+{}'.format(wx, wy, (l-wx)//2, (a-wy)//2))

# *** START APPLICAZIONE ***

if __name__ == '__main__':
    app = FinestraPrincipale()
    app.mainloop()


11
Base / Re:Compilare campi cedola da stampare
« il: Marzo 01, 2019, 12:14 »
Esiste un software con il quale posso misurare esattamente le coordinate di un file immagine su cui poi scrivo?

Intendi un programma qualsiasi per ottenere le coordinate iniziali in cui inerire del testo in una immagine?

Per tale scopo potrebbe essere utile GIMP, un programma di foto-ritocco, scorrendo col mouse su di una immagine nella finestra sono presenti le coordinate correnti del cursore, che possono essere espresse in varie modalità, tra cui pixel (unità base per le immagini) e punti (unità base per i fonts).

In merito alla "precisione", cosa intendi?

12
Database / Re:Somma di alcune colonne
« il: Febbraio 28, 2019, 16:50 »
I miei saluti.

Anche se un po' prematuramente, ho cominciato a vedere qualcosa dei db in python e quasi immediatamente mi sono imbattuto nella pep 249, "Python Database API Specification 2.0", che definisce le specifiche cui devono attenersi i drivers python per le varie basi dati.

Pur se penso che lo OP abbia ormai risolto la sua ultima domanda (cui ho risposto in maniera scherzosa), nel leggere la docs ho visto un particolare secondo me pertinente con la discussione che penso sia il caso di segnalare, altri apprendisti come me potrebbero giovarsene.

Il "particolare" è che un oggetto "cursor" deve esporre dei dati descrittivi del result-set definito dalla query ... a prima vista, ciò "non sembra" particolarmente indicativo, infatti esso espone una serie di tuple contenenti, tra l'altro, il nome della colonna ovvero la funzione applicata su di una colonna, sotto un esempio relativo alla query di interrogazione di base a questo post :

>>> curr = conn.cursor()
>>> curr.execute("""
SELECT nome, SUM(val1), SUM(val2), SUM(val3)
FROM totascio
GROUP BY nome
""")
>>> c_data = curr.description
>>> c_data
(Column(name='nome', type_code=1043, display_size=None, internal_size=10, precision=None, scale=None, null_ok=None), Column(name='sum', type_code=20, display_size=None, internal_size=8, precision=None, scale=None, null_ok=None), Column(name='sum', type_code=20, display_size=None, internal_size=8, precision=None, scale=None, null_ok=None), Column(name='sum', type_code=20, display_size=None, internal_size=8, precision=None, scale=None, null_ok=None))


vi è però l'istruzione sql "AS" che ci permette di denominare "diversamente" un dato od una aggregazione di dati restituita, supposto di voler denominare le somme delle colonne in esempio quali "somma_1 ... somma_n" potremmo porre la query

>>> curr.execute("""
SELECT nome, SUM(val1) AS somma_1, SUM(val2) AS somma_2, SUM(val3) AS somma_3
FROM totascio
GROUP BY nome
""")


una tale query ci permetterebbe di estrarre la descrizione "come vorremmo" che sia definita, in maniera semplice

>>> tv_data = curr.description
>>> c_name = []
>>> for elem in tv_data:
c_name.append(elem[0])


>>> c_name
['nome', 'somma_1', 'somma_2', 'somma_3']


la qual cosa permetterebbe, appoggiandosi ad una variabile intermedia, p.e. una lista, di definire le "tuple" richieste dallo OP

>>> my_data = []
>>> for row in curr.fetchall():
nome, uno, due, tre = row
r_data = [nome, (c_name[1], uno), (c_name[2], due), (c_name[3], tre)]
my_data.append(r_data)

>>> for elem in my_data:
print(elem)


['pippo', ('somma_1', 13), ('somma_2', 12), ('somma_3', 13)]
['ciccio', ('somma_1', 2), ('somma_2', 1), ('somma_3', 10)]
['nino', ('somma_1', 4), ('somma_2', 2), ('somma_3', 1)]
>>>


... certamente si può far di meglio (agli esperti battere il colpo) ma mi sembra un metodo "pratico" per il risultato voluto, oltre quello di definire manualmente dati che si conoscono già, non credo sia il caso di andarsi ad esaminare il "vocabolario" di un db con metodi specifici.

Personalmente, vedo cursor.description utile per eventuali intestazioni di visualizzazioni tabellari dei dati.

13
Ciao a tutti  :) Qualcuno gentilmente potrebbe aiutarmi? Sono agli inizi con Python  :embarrassed:
...
Magari è una cavolata :embarrassed:, ma non ho esercizi svolti da cui poter prendere spunto o farmi anche un'idea e sono agli inizi dello studio.

Se qualcuno volesse darmi anche solo un piccolo aiutino… Grazie anticipatamente  :) Ciao!

Ciao

Premetto che per Tua convenienza è opportuno, prima di chiedere aiuto, provarci, innanzi tutto acquisendo le nozioni necessarie a fare una ipotesi di lavoro e provare a realizzarla, san google aiuta molto a trovare informazioni tipo questa sul leggere/scrivere files di testo, oppure sulle strutture dati disponibili in python.
Dico ciò perché, per esperienza diretta, il non affrontare direttamente il problema inibisce l'assimilazione dei concetti che serve acquisire, fidati, "mettersi" vale 100 volte il "suggerito".

Detto questo, stai ponendo la richiesta di aiuto senza indicare assolutamente nulla, tipo :
- come sono strutturati i file dati da leggere?
- cosa è, esattamente, che devi farci?
Comprenderai che esistono "milioni" di approcci diversi possibili, dipendentemente dalle circostanze.

Ti segnalo, ed invito, a leggere le linee guida per porre compiutamente una richiesta di aiuto, comprendo che Tu sia all'inizio e non le conosca.

Un modo, semplice, per leggere dati da un file di testo lo ho indicato in un recente post, come esempio potrebbe andar bene, vedi un po' se Ti è di aiuto.

Per altro, provaci, poi se hai problemi si è qui. :)

14
if attivo:
IndentationError: unindent does not match any outer indentation level

lo dice l'errore stesso : è dovuto ad errata indentazione.

Python ha una caratteristica peculiare di gestire l'annidamento del codice : utilizza l'indentazione.
Ne consegue, nel codice da Te esposto, che il "continue" invoca un blocco di indentazione che non è stato definito. Dovresti de-indentare di un livello tanto quel continue quanto il blocco "if attivo" e codice seguente, così com'è non dovrebbe funzionare correttamente. Fai molta attenzione alle indentazioni.

Un suggerimento per futuri post : crea un blocco per il codice premendo il pulsante "pythoncode" nella bottoniera ed inserisci il codice tra i tag che vengono generati, sarà molto più chiaro da leggere ed ordinato.

buon lavoro :)

[Edit] Concentrato sull'errore non me ne ero reso conto di :
Citazione
Ora sto provando a leggere salvare in dati = [] anche la riga che contiene la stringa "data".
Così funziona, certo ma ... ripristina com'era e prova ad eliminare proprio il "continue" dal codice, vedi quindi che succede ... Ti servirà ;)

15
Base / Re:Installazione modulo Openpyxl
« il: Febbraio 08, 2019, 08:37 »
Se posso dare una segnalazione, non saprei quanto efficace per il mac

Ho avuto un analogo problema un paio di mesi fa installando le wxPython sul mio sistema linux, ricevevo questo errore :

:~$ pip3 install --user wxPython
Traceback (most recent call last):
File "/usr/local/bin/pip3", line 7, in <module>
from pip._internal import main
ModuleNotFoundError: No module named 'pip._internal'

l'errore era comune, ad ogni tentativo d'uso per installazione di pacchetti, tanto al pip della versione 2.x quanto per la versione 3.x, coesistenti come da default.

dopo alcune ricerche ho risolto scaricando il file get-pip.py da https://bootstrap.pypa.io/get-pip.py e facendo una re-installazione forzata del pip, questo l'output

:~$ sudo python3 get-pip.py --force-reinstall
The directory '/home/nuzzo/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/nuzzo/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting pip
Downloading https://files.pythonhosted.org/packages/c2...y3-none-any.whl (1.3MB)
100% |████████████████████████████████| 1.3MB 172kB/s
Installing collected packages: pip
Found existing installation: pip 9.0.1
Uninstalling pip-9.0.1:
Successfully uninstalled pip-9.0.1
Successfully installed pip-18.1


dalla reinstallazione forzata l'installazione dei pacchetti tramite pip funziona tanto per la versione 2.x quanto per la 3.x di python.

Provando i virtualenv ho visto che torna in auge il pip 9.0.1 sostituito e viene l'errore alla installazione di pacchetti in virtualenv, ogni volta mi tocca reinstallare il pip nel virtualenv.

Ovviamente chiedo ai più esperti di esprimere parere in merito :
suggerirei allo OP di provare in un virtualenv il sistema sopra adottato (in maniera da lasciare integro il sistema base) e vedere se con tale metodo la funzionalità del pip viene ripristinata ... va da se che in un virtualenv non vi è bisogno di re-installazione da superutente.

Pagine: [1] 2 3 4