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.
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
Grazie per l'aiuto.