funzione con tkinter: prima volta ok, successive errore

Linguaggi di programmazione: php, perl, python, C, bash, ecc.

funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » venerdì 3 marzo 2017, 23:41

Avevo fatto una funzione per visualizzare delle foto piu o meno piccole (ma ho visto che la dimensione non è causa del problema) e il risultato è buono. La funzione è in python (non ho usato le classi, ho usato Image.open(thumbnail...) (probabile causa del problema) e canvas.
Se dopo l'utilizzo della funzione, la richiamo nuovamente (stesse foto od altre) , la funzione non va più bene.
Le immagini sono sostituite da un punto interrogativo e l'errore è questo:

Exception AttributeError: "PhotoImage instance has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage instance at 0x7f9bad0cd998>> ignored

Pertanto sono costretto a uscire dal programma per poi richiamarlo.
Probabilmente è qualcosa che resta dopo l'uscita della funzione e che influenza quella chiamata successivamente.
E' possibile risolvere il problema? Non c'è qualche trucco per cancellare tutto tra una funzione e la successiva? Spero di non dover stravolgere la funzione...
Grazie.
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda crap0101 » sabato 4 marzo 2017, 16:53

http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8134
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » sabato 4 marzo 2017, 19:08

Grazie per l'informazione.
Ho letto ma non ho capito quello che devo fare
A dire il vero ho capito un qualcosa che però non funziona:
io ho fatto:
fti = ImageTk.PhotoImage(im)
xlista.append(fti.imageList())
e certamente non è così che devo fare.
Come devo fare?

grazie per l'aiuto
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda crap0101 » sabato 4 marzo 2017, 22:30

http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8134
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » domenica 5 marzo 2017, 11:47

Non mi funziona.

Per provare ho fatto:
fti = ImageTk.PhotoImage(im)
label = Label(image=fti)
label.image = fti
label.grid()
nb: non posso usare pack

ho anche messo come global label,fti (si tenta di tutto!)
va bene la prima volta (anche se la label mi visualizza la foto e mi altera il risultato, ma è per provare) ma quando
richiamo la stessa funzione:

File "9prova0.py", line 5497, in Daimmag
fti = ImageTk.PhotoImage(im)
File "/usr/lib/python2.7/dist-packages/PIL/ImageTk.py", line 110, in __init__
self.__photo = tkinter.PhotoImage(**kw)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3329, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3285, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: can't invoke "image" command: application has been destroyed
Exception AttributeError: "PhotoImage instance has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage instance at 0x7f6cbdc13368>> ignored

Sbaglio tutto ma non capisco dove...
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » lunedì 6 marzo 2017, 20:09

ho fatto ancora altre prove, ma non ho risolto niente,
Se non si riesce a risolverlo c'è qualche nodo per aggirarlo?
Io avevo pensato di fare un programma con la sola funzione, ma passargli i vari parametri e ricevere I vari risultati è piuttosto macchinoso.
C'è qualche altro modo?,
grazie,
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda crap0101 » martedì 7 marzo 2017, 22:25

forse allora c'è qualcos'altro che non va, magari proprio come è impostato il codice...
prova questo, che fa esattamente quello descritto nei link (e senza usare pack() ):
Codice: Seleziona tutto
crap0101@orange:/tmp/foo$ cat x.py
import itertools
from PIL import Image, ImageTk
import sys
import Tkinter

def foo(label):
    image = Image.open(next(imgs))
    photo = ImageTk.PhotoImage(image)
    label.config(image=photo)
    label.image = photo # keep a reference!
    label.grid()

if __name__ == '__main__':
    imgs = itertools.cycle(sys.argv[1:])
    master = Tkinter.Tk()
    l = Tkinter.Label(master)
    b = Tkinter.Button(master, text="foo", command=lambda: foo(l))
    b.grid()
    master.mainloop()

lo esegui con una serie di immagini come argomenti e, premendo ripetutamente il bottone, visualizzi le immagini in ciclo
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8134
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » sabato 11 marzo 2017, 10:29

Ti ringrazio e mi scuso per il ritardo (a causa di grossi problemi imprevisti)
Ho provato il tuo programmino e funziona (non avevo dubbi!) ma non sono riuscito ad applicare
la soluzione alla mia funzione (di molto tempo fa, piuttosto corposa perchè ha tante opzioni, e che
non mi sento di riscriverla stravolgendola)
Essenzialmente con canvas crea una griglia (più o meno grande) con delle miniature di foto
con la possibilità di spostarle, contrassegnarle ed altro
La parte critica è Daimmag(), che in un uso successivo della funzione va in errore, anche
se non sempre (garbage?)
L'ossature della funzione è quella della costruzione della griglia (riporto solo le
istruzioni più importanti)

Codice: Seleziona tutto

#------------------------- funzione che genera l'errore
   def Daimmag(nm):
      ten=0
      while ten<3:
         nmthu=THUMB(nm); se=1
         try:
            im = Image.open(nmthu)
            rid=1.85; a= im.size
            ww=a[0]; hh=a[1]
            if hh>ww: rid=1.5
            ridx=rid*Coe
            if ridx <> 0: im=IMAGERESIZE(im,r=ridx)
            fti = ImageTk.PhotoImage(im)
            ten=3
         except:  fti="?"; ten+=1   
      return fti

#-------------------------  elementi base (non tutto) della funzione                 
   foto = tk.Tk()
   end1=0
   while end1==0:

# valori diversi in base alla dimensione miniatura:  Grig=dimensione, base=posizionamento in basso
#  ed altre cose.....

      canvas = tk.Canvas(foto, width=Wid, height=Hei, highlightthickness=0,bg="#046F04")    # colore griglia
      canvas.configure(scrollregion=(0, 0, Wid-1, Heitot-1))
      canvas.grid(row=0, column=0)
      yscrollbar = tk.Scrollbar(foto)
      yscrollbar.grid(row=0, column=1, sticky="ns")
      yscrollbar.config(command=canvas.yview)
      canvas.config(yscrollcommand=yscrollbar.set)
      for r in range(Rows):                                             # caricamento griglia
        for c in range(Cols):
           y = r * Grid; x = c * Grid
           colore = "#FFFFF1"
           canvas.create_rectangle(x+3, y+3, x+Grid-4, y+Grid-4, fill=colore)
#
# caricamento delle foto
#         
      for nf,nm in enumerate(Tbf):                                      # caricamento immagini thumb in Ti
           if siti==1:
              fti=Daimmag(nm)
              Ti.append(fti)
#~



Confesso di non aver capito bene perchè una funzione che ha evidenziato una griglia con delle foto, se richiamata nuovamente con altre foto vada in errore. Concettualmente l'idea è che una funzione se richiamata più volte, dovrebbe
non avere nulla a che fare con un uso precedente... Si è portati a credere che ogni volta tutto riinizi...
Purtroppo non è così, e questo mi è chiaro!
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda crap0101 » lunedì 13 marzo 2017, 14:19

vedere anche il resto potrebbe essere utile.. a parte questo, nella funzione vedo variabili temporanee e soprattutto, non vedo dove applichi quanto detto prima
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8134
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » lunedì 13 marzo 2017, 16:00

Come già detto la funzione è stata fatta diverso tempo fa, ma fa bene le cose per cui è stata fatta.
Per te sicuramente avrà uno stile di programmazione pessimo e forse incomprensibile, ma questo è quanto di meglio ero riuscito a fare (autodidatta e certamente non giovincello... gli anni iniziano per 8 e non ne ho 8!))

La funzione ha diversi usi e quindi ha molti parametri. Usa delle altre funzioni ma sono abbastanza comprensibili (THUMB ad esempio crea la thumbnail in threading se serve e non ci sono già, DFDATAF per le date sui file, MENU per una lista da visualizzare o per delle scelte, ecc.)
Gli usi principali della funzione sono: per contrassegnare delle foto, ordinarle spostandole (naturalmente una successiva funzione le rinomina per mantenerle nella nuova sequenza), ruotarle, eliminarle ecc.

Questa è la funzione:

Codice: Seleziona tutto
def FOTOMINI(Tbf,posiz=0,tit="",mds="r",mdd="v",funz="RE",mdv=1,Tbs=[],Tbe=[],msevid="",misevid="",cod="",ind=0):
#           Tbf,Tbs,Tbe,exi=
#> 12-03-2017 10:02:50    #FO visualizzazione miniature foto a mosaico:   
#--
#    Tbf    : lista con nomi foto   (es: ["/MIEI-FOTO/M-Bianco/ft-001.JPG", ecc"
#             oppure  percorso fino alla cartella foto - nb: deve essere esistente
#    posiz  : posizionamento iniziale sulla foto n - se diverso da 0, la foto viene evidenziata in lilla
#             se -posiz: viene evidenziata solo all'inizio
#    tit    : eventuale titolo
#    mds    : "" , "r", "v", "X", "?"  per ts Sx  (r marca in Rosso, v verde, X exit, XC exit con conferma, "?" chiede (vedi sotto)
#    mdd    : come mds ma per ts destro
#             '?' in mds (o mdd): chiede quanto indicato in msevid e lo memorizza in Tbe (evid. in riga 3) - @ = contatore
#             se '?' senza 'r' o 'v' il ts. premuto provoca la cancellazione del testo abbinato
#    funz   : abilitazione funzioni: 'R'  rotazione foto   con Ctrl+ts Sx e ctrl+ts Dx
#                                    'E'  eliminaz. foto   con Ctrl+Alt+ts. Sx
#                                    'S'  spostamento foto con Ctrl+Alt+ts. Dx - fa spostare dietro la foto tutte
#                                             le foto già marcate con il ts. sx, mantenendo l'ordine di marcatura
#    mdv    : grandezza foto da visualizzare: 0=maxi, 1=normale, 2=mini, 3=micro
#    Tbs    : event.tabella con attributi della foto allineata a Tbf (es: ["3","","","|5,|72","","1|2",...] )
#    Tbe    : eventuale lista abbinata a perc con informazioni da evidenziare (in blu) sotto il nome
#    msevid : eventuale messaggio di richiesta usato se '?' in mds o mdd
#               se come richiesta si mette @: l'uso dei tasti riporta su Tbe l'ultimo num.di contatore usato
#               nb: quanto registrato è cancellabile solo con una sovrascrittura
#    misevid: eventuale messaggio informativo per IPTX do msevid (righe con \n)
#    cod    : codice per richiamare txt,cl=FOTOMINI_x(cod,nf,Tbf[nf])    codice, num.foto, perc.foto
#             se si mette qualcosa in txt (e un colore in cl) verranno visualizzata in seconda riga delle foto
#             Es:   def FOTOMINI_x(cod,nf,percft):
#                       txt=cl=""
#                       ------- elaborazione -------> txt="xxxxxx"; cl="#0BB522"   (compariranno in riga 2)
#                       return txt,cl
#    ind    : se maggiore di 0: visualizza prima un indice per una scelta ridotta (minimo ind: 50)
# << Tbf    : lista nomi foto (percorsi) - modif. se 'S' (sequenze)
# << Tbs    : lista selezioni fatte: nsin |ndes nsin|ndes  (se 'S' solo selez. ultimo sort
# << Tbe    : lista dati extra - modif. se 'S' (sequenze) o se usato '?' +msevid
# << exi    : "x" (uscita con 'x')  oppure  '<' o '>'  se  exit con ts sx dx,  'e' se exit con Escape
#              in PYw lista con:[0]: num.foto in Tbf,
#                               [1]: ultimo num.contat.usato
#                               [2]: 'E','S','E'+'S' se Tbs modificato ('S' file da rinumerare e riscrivere)
#-----
# richiede: from PIL import Image, ImageTk, ImageFilter
# uso:       Visualizza le miniature in 4 formati possibili (con freccia < e > si può variare) - scroll griglia foto
#            nb: In apertura se le foto sono molte richiede tempo
#            pernmette di selezionare usando mouse Dx e Sx: le selezioni fatte e l'ordine di selezione sono disponibili
#            in Tbs una riga x ogni foto): (nnn, |nnn, nnn|nnn)  ts.sx,dx.sn e ds   nnn num.progressivo di selezione -
#            i tasti devono essere abilitati e marcheranno in rosso o verde secondo quanto indicato in mds, mdd
#            se im mdm/mds si mette anche X il tasto provocherà l'uscita XC uscita previa conferma
#            se si mette 'S' in funz si possono spostare (sequenza) come desiderato
#            se si mette 'R' in funz si possono ruotare come desiderato
#            clickando 'p' o 'g' o 'x' sull'immagine si può modificare la foto con 'pinta' / 'gimp' / 'fotoxx'
# KF= visualizzazione foto thumbnail miniature
#------------------------------------------------------------------------------
   global PYww, PYw                                                                                             # usate da tutte le mie funzioni per usi diversi
   def Daimmag(nm):
      ten=0
      while ten<3:
         nmthu=THUMB(nm); se=1
         try:
            im = Image.open(nmthu)
            rid=1.85; a= im.size
            ww=a[0]; hh=a[1]
            if hh>ww: rid=1.5
            ridx=rid*Coe
            if ridx <> 0: im=IMAGERESIZE(im,r=ridx)
            fti = ImageTk.PhotoImage(im)
            ten=3
         except:  fti="?"; ten+=1                                          #; se=0
      return fti
#----
   def clickx(h, y, x, ys):                                             # h= 'p' 'g' 'x'   per pinta, gimp, fotoxx
      global PYww
      y = (y + ys*Heitot) // Grid
      x //= Grid
      nf=int(y*Cols+x)                                                  # determina num.foto
      if nf>=len(Tbf): return
      ff=Tbf[nf]
      ff=ff.split(PYsep,1)[0]
      if h=="p": pro="pinta "
      elif h=="x": pro="/usr/bin/fotoxx "
      else: pro="gimp "
      os.system(pro+ff)
      if h=="x":
         cart=ff.rsplit("/",1)[0]+"/.thumbnails"
         if DF(cart,"d"): DDELETE(cart)
      fti=Daimmag(ff)
      Ti[nf]=fti
      Fotog(nf,Tbf,Ti,Tbs,Tbe,colo="")
      return
#----
   def Conf(md):
      if "C" in md:
         x=tkMessageBox.askyesno("Confermi uscita?")
         if x == False: return 0
      return 1
#----
   def click(h, y, x, ys):
      global PYww
      y = (y + ys*Heitot) // Grid
      x //= Grid
      nf=int(y*Cols+x)                                                  # determina num.foto
      if nf>=len(Tbf): return
      nm=Tbf[nf]; nm=nm.split("|",1)[0]                                 # se file = /xx/xx/xx|yyyy
      nmf=nm.rsplit("/",1)[1]                                           # nome file
      fu=""
      fu=h[1:2]; h=h[0:1]
      if fu not in funz: return
      if h=="=":
         FEH([nm])                                                      # 1 foto in full screen
         dat,x=DFDATAF(nm)
         nm=nm.rsplit("/",1)
         car=nm[0]
         nm=nm[1]
         info=[" ","  Informazioni:}L",""
              ,"cartella  : "+car+"}M"
              ,"foto      : /"+nm+"}B"
              ,"data      : "+dat+"}B"
              ,"posizione : "+str(nf)
              ," "
              ,"Tbf       : "+Tbf[nf]
              ,"Tbs       : "+Tbs[nf]
              ,"Tbe       ; "+Tbe[nf]
              ]
         MENU(info)
         return
      seint=""
      if (h=="<" and "?" in mds): seint=mds.strip()
      if (h=='>' and "?" in mdd): seint=mdd.strip()                     # se msevid, chiede...
      if fu=="R":                                                       # R ruota
         if h=="<": FOTOGIRA("s",Tbf[nf],Tbf[nf])
         else:      FOTOGIRA("d",Tbf[nf],Tbf[nf])
         nm=Tbf[nf]
         fti=Daimmag(nm)
         Ti[nf]=fti
         Fotog(nf,Tbf,Ti,Tbs,Tbe)
         return
      if fu=="E":                                                       # E elimina e prem ts in
         x=tkMessageBox.askyesno("per conferma", 'Vuoi veramente eliminare la foto?\n'+"("+str(nf+1)+" - "+nmf+")")
         if x == False: return
         PYww[0]="E"; PYww[4]=nf
         foto.quit()
         return
      if fu=="S":                                                       # S sposta foto
         w1=[]
         for nn,ss in enumerate(Tbs):
             if nn==nf:da=nn-len(w1); continue
             ss=ss.replace("|","")
             if ss=="": continue
             rec="0000"+str(nn); seq="0000"+ss; rec=rec[-4:]; seq=seq[-4:]
             w1.append(rec+"|"+seq)
         PYww[0]="S"; PYww[4]=w1;  PYww[5]=da
         foto.quit()
         return
      if seint<>"":
         if "r" not in seint and "v" not in seint: Tbe[nf]=""
         else:
            if "@" in msevid[1:3]: Tbe[nf]=h+" "+str(PYww[2]+1)         # contatore. < nnnn o < nnnn
            elif msevid<>"":
               x=msevid; ori=y=Tbe[nf]; y=y.lstrip("<"); y=y.lstrip(">"); y=y.lstrip()
               rc,z=IPTX(x,[y],lu=75,msg=misevid)
               z=z[0]
               if rc<>0:
                  z=z.strip()
                  if z[0:1]=="#": Tbe[nf]=""                            #  '#'  cancella testo
                  else: Tbe[nf]=z
      if fu=="":
         mark=Tbs[nf]
         marks,markd=Daisd(mark)
         see=0
         if h=="<":
            if 'X' in mds: see=Conf(mds)
            if 'r' in mds or 'v' in mds:
               if marks=="": PYww[2]+=1; marks=str(PYww[2])             # < - incrementa contatore e marca
               else: marks=""                                           #     o rimuovi
         if h==">":
            if 'X' in mdd: see=Conf(mdd)
            if 'r' in mdd or 'v' in mdd:
               if markd=="": PYww[2]+=1;  markd=str(PYww[2])            # > - incrementa contatore e marca
               else: markd=""                                           #     o rimuovi
         w=marks+"|"+markd; Tbs[nf]=w.rstrip("|")
         Fotog(nf,Tbf,Ti,Tbs,Tbe)
         if see==1: PYww[0]=h; PYww[1]=nf; foto.destroy(); return       # se 'X'  esci
         return
      return
#----
   def clickf(h):                                                       # curs-sin/ds  foto + grandi/ + piccole , Escape
      global PYww
      PYww[0]=h                                                         # h= G/P/e
      foto.destroy()
#-----
   def clickp(h):                                                       # curs-sin/ds  foto + grandi/ + piccole
      foto.quit()
#------------------------------------------------
   def Daisd(mark):                                                     # separa uso ts.sx dal dx
      mark=mark.split("|",1); marks=mark[0]; markd=""
      if len(mark)>1: markd=mark[1]
      return marks,markd
#-----
   def Fotog(nf,Tbf,Ti,Tbs,Tbe,colo=""):                                # porta la foto sulla canvas
      Nom=Tbf[nf]; Nom=Nom.rsplit("/",1)[-1]; Nom=Nom.rsplit(".",1)[0]
      Xim=Ti[nf]
      Sce=Tbs[nf]
      mark=Tbs[nf]
      marks,markd=Daisd(mark)
      Info=Tbe[nf]
      r=nf/Cols; c=nf-(r*Cols)                                          # dal num.foto ricava riga e colonna x posizionamento
      y = r * Grid; x = c * Grid
      colore="#EEEEEE"
      if colo<>"": colore=colo
      try:
         canvas.create_rectangle(x+3, y+3, x+Grid-4, y+Grid-4, fill=colore)
         canvas.create_image(x+(Grid//2),y+(Grid//2+Base), image=Xim)
      except:
         try: canvas.create_text(x+(Grid//2), y+(Grid//2), text="?", font=(fon,18,'bold'), fill="#A52A2A",anchor="w")
         except:  return "X","X"
      txt=LU(Nom,Rig1l,"t")
      Num=str(nf+1)+ ": "
      canvas.create_text(x+6, Rig1+y, text=Num, font=(fon,Fmis,'bold'), fill="#FF00E9",anchor="w")
      txt=Nom
      canvas.create_text(x+Grid//2+len(Num), Rig1+y, text=txt, font=(fon,Fmis,'bold'), fill="#000000")
      if cod<>"":
         try:  txt,cl=FOTOMINI_x(cod,nf,Tbf[nf])
         except: txt=""
         if txt<>"":
            txt=LU(txt,Rig2l,"t")
            if cl=="": cl="#FF0000"
            canvas.create_text(x+Grid//2, Rig2+y, text=txt, font=(fon,Fmis-1,'bold'), fill=cl)
      if Info <> "":
          txt=LU(Info,Rig2l,"t")
          canvas.create_text(x+Grid//2, Rig3+y, text=txt, font=(fon,Fmis-1,'bold'), fill="#4B4BFD")

      if 'r' in mds: colore="r"
      else: colore="v"
      if marks<>"": Marca(nf,Grid,x,y,'<',colore)
      if 'r' in mdd: colore="r"
      else: colore="v"
      if markd<>"": Marca(nf,Grid,x,y,'>',colore)
      return marks,markd

#-----
   def Marca(nf,Grid,x,y,sd,colore):
      r=nf/Cols;    c=nf-(r*Cols);   w=4
      y = r * Grid; x = c * Grid
      if colore=="r": colore="#FF0000"
      if colore=="v": colore="#00FF2E"
      if sd==">":
         canvas.create_line(x+Grid*0.5,y+Grid*0.3, x+Grid-6, y+Grid*0.65, fill=colore,width=w)
         canvas.create_line(x+Grid*0.5,y+Grid,     x+Grid-6, y+Grid*0.65, fill=colore,width=w)
      if sd=="<":
         canvas.create_line(x+Grid*0.5,y+Grid*0.3, x+4, y+Grid*0.65, fill=colore,width=w)
         canvas.create_line(x+Grid*0.5,y+Grid,     x+4, y+Grid*0.65, fill=colore,width=w)
      return

   def xprima():                            # per 'X' prima della fine
      global PYerror,PYww
      PYerror=1
      return

   def AAA(): return
#----------------------------------------------------------------
   global PYerror
   shelp=""
   if funz <> "":
      msg=""
      if "R" in funz: shelp+="R"; #msg+="Ctrl+ts.Sx      per ruotare foto verso sinistra\nCtrl+ts.Dx                       verso destra\n"
      if "E" in funz: shelp+="E"; #msg+="Ctrl+Alt+ts.Sx  per eliminare la foto cliccata}R\n"
      if "S" in funz: shelp+="S"; #msg+="Ctrl+Alt+ts.Dx  per spostare le foto marcate dopo la foto cliccata}B\n"
   PYww=["x",-1,0,"","","",""]                                          # exit, n,foto, ctr, 's' se modif.seq.
   if type(Tbf)==type(""):                                              # se no lista foto
      ELDF(Tbf,"p")
      Tbf=PYfile[:]
   nuft=len(Tbf)
   if nuft==0: H(91,"FOTOMINI: ipt 0 foto"); return [],[],[],""
   if len(Tbs) < nuft: Tbs=Tbs+[""]*(nuft-len(Tbs))                     # allinea Tbs e Tbe
   else: Tbs=Tbs[0:nuft]
   if len(Tbe) < nuft: Tbe=Tbe+[""]*(nuft-len(Tbe))
   else: Tbe=Tbe[0:nuft]
   Tbfp=[]; Tbfd=[]; Tbsp=[]; Tbsd=[]; Tbep=[]; Tbed=[];
   if ind > 49 and len(Tbf) > ind:
      Tbf,Tbfp,Tbfd,posi,Tbs,Tbsp,Tbsd,Tbe,Tbep,Tbed=FOTOPARZ(Tbf,posi=0,Tbs=Tbs,Tbe=Tbe)
   if tit=="":
      if type(Tbf)==type([]): tit=Tbf[0].rsplit("/",1)[0]
      else: tit=Tbf
   tito="ft:"+str(nuft)+" - "+tit
   Ti=[]
   foto = tk.Tk()
   foto.title(tito)
   end1=0
   while end1==0:
# valori diversi in base alla dimensione miniatura:  Grig=dimensione, base=posizionamento in basso
#              Fmis=misura font, Rig1,2,3=posiz.riga txt 1,2,3,rig1l,2l=lungh.max txt, coe ingr.miniatura
      if mdv==0: Grid=380; Base=30; Fmis=11;Rig1=16; Rig2=35; Rig3=54; Rig1l=33; Rig2l=38; Coe=2.35
      if mdv==1: Grid=180; Base=22; Fmis=9; Rig1=12; Rig2=27; Rig3=39; Rig1l=20; Rig2l=20; Coe=1
      if mdv==2: Grid=120; Base=16; Fmis=8; Rig1=12; Rig2=23; Rig3=31; Rig1l=14; Rig2l=13; Coe=0.7
      if mdv==3: Grid=65;  Base=8;  Fmis=5; Rig1=7;  Rig2=13; Rig3=18; Rig1l=10; Rig2l=10; Coe=0.33
      Cols=int(PYlar/Grid)                                                 # num.colonne possibili
      Rows=int(nuft+Cols-1)/Cols                                           # num.righe necessarie
      Righev=int(PYalt/Grid)                                               # righe visualizzate in una videata
      Wid = Grid * Cols                                                    # larghezza canvas
      Hei = Grid * Righev                                                  # altezza visualizzata
      Heitot = (Grid * Rows)+Grid/2 +1                                     # altezza totale da scorrere
      fon="Roman"
      canvas = tk.Canvas(foto, width=Wid, height=Hei, highlightthickness=0,bg="#046F04")    # colore griglia
      canvas.configure(scrollregion=(0, 0, Wid-1, Heitot-1))
      canvas.grid(row=0, column=0)
      yscrollbar = tk.Scrollbar(foto)
      yscrollbar.grid(row=0, column=1, sticky="ns")
      yscrollbar.config(command=canvas.yview)
      canvas.config(yscrollcommand=yscrollbar.set)
      for r in range(Rows):                                             # caricamento griglia
        for c in range(Cols):
           y = r * Grid; x = c * Grid
           colore = "#FFFFF1"
           canvas.create_rectangle(x+3, y+3, x+Grid-4, y+Grid-4, fill=colore)
      ult=-1; siti=0
      if Ti==[]: siti=1
      xca=xxca=35
      PYerror=0    # x 'X' premuto prima della fine
      for nf,nm in enumerate(Tbf):                                      # caricamento immagini thumb in Ti
           if siti==1:
              fti=Daimmag(nm)
              Ti.append(fti)
           marks,markd=Fotog(nf,Tbf,Ti,Tbs,Tbe)
           if marks=='X'and markd=='X': break
           if marks<>"" and int(marks)>ult: ult=int(marks)
           if markd<>"" and int(markd)>ult: ult=int(markd)
           nc=Cols; nc0=nc+0.0; nfp=nf+1
           if nfp/nc0 == int(nfp/nc):
              foto.after_cancel(0)
              action2=lambda nn=1:clickp('p')
              foto.after(int(1),action2)
              foto.protocol("WM_DELETE_WINDOW",xprima)
              if PYerror==1: end1=1; print 1111; break
              foto.mainloop()                                           # prima visibilità a 40 foto
              xca+=xxca
      foto.protocol("WM_DELETE_WINDOW",())
      if end1==1: PYww[0]="e"; foto.destroy(); break
      foto.bind("<KeyPress-p>", lambda ev: clickx("p",ev.y, ev.x, yscrollbar.get()[0]))           # 'p': pinta
      foto.bind("<KeyPress-x>", lambda ev: clickx("x",ev.y, ev.x, yscrollbar.get()[0]))           # 'x': fotoxx
      foto.bind("<KeyPress-g>", lambda ev: clickx("g",ev.y, ev.x, yscrollbar.get()[0]))           # 'g': gimp
      canvas.bind("<Button-1>", lambda ev: click("<",ev.y, ev.x, yscrollbar.get()[0]))
      canvas.bind("<Button-2>", lambda ev: click("=",ev.y, ev.x, yscrollbar.get()[0]))            # mouse centrale: full
      canvas.bind("<Button-3>", lambda ev: click(">",ev.y, ev.x, yscrollbar.get()[0]))
      canvas.bind("<Control Button-1>", lambda ev: click("<R",ev.y, ev.x, yscrollbar.get()[0]))   # ctrl+mouse Sx:  ruota sinistra
      canvas.bind("<Control Button-3>", lambda ev: click(">R",ev.y, ev.x, yscrollbar.get()[0]))   # ctrl+mouse Dx:  ruota destra
      canvas.bind("<Shift Button-1>", lambda ev: click("<3",ev.y, ev.x, yscrollbar.get()[0]))     # Maiusc+mouse Sx    non usato
      canvas.bind("<Shift Button-3>", lambda ev: click(">4",ev.y, ev.x, yscrollbar.get()[0]))     # Maiusc+mouse Dx    non usato
      canvas.bind("<Alt Button-1>", lambda ev: click("<E",ev.y, ev.x, yscrollbar.get()[0]))       # Alt+mouse Sx:   elimina
      canvas.bind("<Alt  Button-3>", lambda ev: click(">S",ev.y, ev.x, yscrollbar.get()[0]))      # Alt+mouse Dx:   sposta
      foto.bind("<Left>",  lambda ev: clickf("P"))                                                # freccia sx:     foto + piccole
      foto.bind("<Right>", lambda ev: clickf("G"))                                                # freccia dx:     foto + grandi
      foto.bind("<Escape>", lambda ev: clickf("e"))                                               # Escape:         termina
      foto.bind("<F1>", lambda ev: HELP("H","FOTOMINI",shelp))                                    # F1:             help
      canvas.bind("<Button-4>", lambda ev: canvas.yview_scroll(-5, "units"))                      # mouse rotella in su:  scorrimento in su
      canvas.bind("<Button-5>", lambda ev: canvas.yview_scroll(5, "units"))                       # mouse rotella in giu: scorrimento in giu
      PYww[2]=ult
      if posiz<>0:
         if posiz<len(Tbf):                                             # evidenzia foto di partenza
            q=abs(posiz)-1; qr=q/Cols; qc=q-(qr*Cols)
            if q+1 > (Righev-1)*Cols:
               z=qr*2
               canvas.yview_scroll(z, "units")
            Fotog(q,Tbf,Ti,Tbs,Tbe,"#F8F8BC")
      foto.mainloop()
      if PYww[0]=="S":                                                  # sequenza
         w1=PYww[4]; da=PYww[5];  w3=[];w4=[];w5=[];w6=[]
         w2=reversed(w1)
         for x in w2:  w=int(x[0:4]); w3=[Tbf.pop(w)]+w3; w4=[Ti.pop(w)]+w4; w5=[Tbe.pop(w)]+w5
         for n,x in enumerate(w1):  w6.append(x[5:]+"|"+str(n+10000)[-4:])
         w6=sorted(w6)
         nn=1
         for x in w6: n=int(x[5:]); Tbf.insert(da+nn,w3[n]); Ti.insert(da+nn,w4[n]); Tbe.insert(da+nn,w5[n]);  nn+=1
         PYww[0]="x"; PYww[4]=""; PYww[5]="";
         if 'S' not in PYww[3]: PYww[3]+="S"
         Tbs=[""]*len(Tbf)
         continue
      if PYww[0]=="E":                                                  # eliminazione
         nf=PYww[4]
         ww=Tbf.pop(nf); Tbs.pop(nf); Ti.pop(nf); Tbe.pop(nf);
         FDELETE(ww)
         if 'E' not in PYww[3]: PYww[3]+="E"
         PYww[0]="x"
         posiz=nf
         tito="ft:"+str(len(Tbf))+" - "+tit
         foto.title(tito)
         continue
      if PYww[0]=="G" or PYww[0]=="P":                                  # cambia misura foto
         foto = tk.Tk()
         foto.title(tit)
         Ti=[]
         if PYww[0]=="P":mdv+=1
         else: mdv-=1
         if mdv<0: mdv=0
         if mdv>3: mdv=3
         PYww[0]="x"
         continue
      else: end1=1
   exi=PYww[0]; PYw=PYww[1:4];
# exi    : "x" (uscita con 'x')  oppure  '<' o '>'  se  exit con ts sx dx,  'e' se exit con Escape
# PYw: [0]: num.foto in Tbf, [1] ultimo num.contat.usato, [2]: 'E','S','E'+'S' se Tbs modificato ('S' file da rinumerare e riscrivere)
   Tbf=Tbfp+Tbf+Tbfd
   Tbs=Tbsp+Tbs+Tbsd
   Tbe=Tbep+Tbe+Tbed
   PYw[0]=len(Tbf)                        # PYw[0]+=len(Tbfp)
   THUMB("")                          #chiude eventuale threading
   return Tbf,Tbs,Tbe,exi



Non so se riuscirai a raccapezzarti. Spero di si....

Io ho tentato in molti modi di risolvere il problema, ma sinceramente senza aver ben chiaro quello che dovevo fare.
I soliti tentativi che non servono a nulla.
Per ora io ho risolto la cosa usando un piccolo programma esterno che ha solo questa funzione e alla quale (e dalla quale) sono passati i dati con Pickle
Ma certamente è una soluzione pessima!

Grazie per l'aiuto.
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008

Re: funzione con tkinter: prima volta ok, successive errore

Messaggioda maresama » martedì 21 marzo 2017, 17:35

Ho scoperto una cosa:
Poichè ricordavo che non sempre c'era l'errore, ho voluto capire perchè.
Usando la stessa funzione con gli stessi input, due volte (una di seguito all'altra) :
uscendo con 'X' dalla prima, la seconda dava errore.
uscendo con un comando diverso (es. Escape) la seconda andava bene e non dava errore.

Allora ho provato a sostituire il comando:
foto.protocol("WM_DELETE_WINDOW",())
con:
foto.protocol("WM_DELETE_WINDOW", ExitX)
e creata la callback:
def ExitX():
x=tkMessageBox.askyesno("Confermi uscita?")
if x == True: foto.destroy()
Incredibilmente ora non da più errore.

Apparentemente ora funziona tutto (dovrò fare molte altre prove....)

Ma quello che non ho capito:
1 - perchè prima non andava
2 - perchè ora va bene (Io non ho fatto altre modifiche e l' errore (dovuto alla garbage...) dovrebbe ancora esserci!

Unica cosa che ho capito è che tkinter io non lo capisco.....
maresama
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1396
Iscrizione: gennaio 2008


Torna a Programmazione

Chi c’è in linea

Visualizzano questa sezione: 0 utenti registrati e 9 ospiti