Forum
>>
Principianti
>>
problemi con programmino
Pagina: 1
Esegui il login per scrivere una risposta.
Pagina: 1
Scritto da tex_si |
2015-10-19 12:37:20 - problemi con programmino
|
Ho modificato ed adattato questo programmino trovato su "Programming Python" O'Reilly, Mark Lutz, per esercitarmi con Python.
Il problema è che il tasto "load" funziona solo se faccio partire il programma con "edit with IDLE" --> "run"-->"run module", se lo faccio partire con il doppio click mi apre la finestra di dialogo e come clicco su apri crasha. Perché? Perché il pulsante "quit" non funziona? E' possibile non far comparire la finestra nera "C:\Windows\py.exe" quando lancio il programma? Grazie in anticipo dell'aiuto. |
|
Scritto da tex_si |
2015-10-26 15:30:13 - Re: problemi con programmino
|
Ho risolto il problema del tasto quit usando:
command=root.destroy Inspiegabilmente ora la funzione load non crasha più quando lancio il programma con un doppio click. |
|
Scritto da Claudio_F |
2015-10-27 09:38:09 - Re: problemi con programmino
|
Mi sembra che ci siano diversi errori in quel codice. Sicuramente quit con le parentesi di chiamata. Poi la chiamata a mainloop senza specificare l'oggetto su cui chiamarlo (solitamente l'istanza root di Tk...). Anche l'uso di forget mi sembra strano, i widget vengono "dimenticati" dal gestore grafico (non vengono più visualizzati fino a eventuale successivo pack/grid/place), ma non eliminati.
Il differente comportamento tra il lancio diretto del programma e da dentro Idle si può spiegare con il fatto che lo stesso ambiente Idle è un programma grafico Tk, e il tuo viene lanciato all'interno di esso come thread figlio (ad esempio se un'applicazione Tk che crea thread demoni viene lanciata all'interno di Iidle, i thread demoni non muoiono finché non viene chiuso totalmente Idle stesso). Il fatto che lanciando il programma con il doppio click si chiuda subito, significa che c'è un errore che Idle maschera (sospetto fortemente quel mainloop da solo). Il modo corretto per vedere gli errori e non avere effetti di "silenziamento" dovuti a un IDE è lanciare il programma dalla console comandi scrivendo per esteso: python nomeprogramma.py (con windows è un po' brigoso, bisogna aggiungere il nome dell'interprete al path di sistema e spostarsi a manina nella subdir contenente il programma). Per la "finestra nera" (la console comandi) forse basta rinominare i .py in .pyw *** Il codice va evidenziato con il simbolo di fianco ai colori per non perdere l'indentazione *** |
|
Scritto da tex_si |
2015-10-27 12:01:04 - Re: problemi con programmino
|
Adesso funziona tutto.
Rinominando il file, come mi hai suggerito, ha funzionato alla grande. Grazie . Non credo di avere la preparazione sufficiente per capire a fondo gli errori che mi hai segnalato (ho studiato su "programmare con Python" di Mark Lutz e David Ascher della Hoepli informatica O'Reilly(per la sintassi base) e su "programming Python" 3rd Edition di Mark Lutz della O'Reilly (che da per scontato che si conosce la sintassi base e approfondisce alcuni argomenti come la creazione di interfacce grafiche con tkinter), ma per adesso li ho appena letti non studiati a fondo). Comunque, stranamente, dopo che ho sostituito <> command=self.quit() <> con <>command=root.destroy<>, non solo funziona il tasto quit, ma non crasha più quando uso il tasto load (non so proprio spiegarmi il perché). Comunque ora funziona tutto, allego la versione del file completamente funzionante. Grazie ancora di tutto l'aiuto ricevuto. |
|
Scritto da Claudio_F |
2015-10-27 14:48:09 - Re: problemi con programmino
|
Per praticità gli esempi sui libri importano (quasi) sempre tutto il contenuto dei moduli, quindi fanno un bel
from tkinter import *ma non sarebbe una cosa da fare perché tutto quello che è definito nel modulo diventa visibile a livello globale, basta fare from tkinter import * dir()per accorgersi di quenti nomi, funzioni, costanti siano state importate. Questo vuol dire ad esempio non poter definite una nostra costante END perché andremmo a sovrascrivere quella importata. Se invece si importa solo il nome del modulo e ci si riferisce alle cose contenute tramite nomemodulo.cosaconenutanon avremo mai conflitti tra nomi. Tra l'altro il famoso 'mainloop' che dicevo è una funzione importata assieme a tutto il resto, per quello funziona, altrimenti si doveva scrivere (più correttamente) root.mainloop() Per quanto riguarda 'quit()' il problema sono le parentesi di chiamata alla funzione quit. A command si assegna il nome della funzione da eseguire (giustamente root.destroy), non il risultato della chiamata alla funzione (anche root.destroy() non andrebbe bene). La logica nella funzione 'onload' invece è sbagliata (lo si dovrebbe notare da un'estrema lentezza nell'aggiornamento delle celle). Le entry vanno distrutte e ricreate ex novo (meglio ancora sarebbe fare questo solo se cambia il numero di colonne o righe), ho perciò corretto un po' il codice come spunto. Non è ancora perfetto (basta lasciare una casella vuota per accorgersene) e si potrebbe discutere sul design scelto dagli autori (sempre per ragioni di semplicità espositiva), ad esempio il nome 'root' globale... tra l'altro anche subclassare Frame in quel modo non mi sembra una cosa adatta ad un esempio per principianti (a meno che l'esempio non riguardi il subclassamento ovviamente). Nota: gli import iniziali rendono il tutto compatibile con Python2. try: import tkinter as tk import tkinter.filedialog as filedialog except ImportError: import Tkinter as tk import tkFileDialog as filedialog import os class portaeppendorf(tk.Frame): def __init__(self, parent=None, numrow=10, numcol=10): tk.Frame.__init__(self, parent) self.numrow = numrow self.numcol = numcol self.makewidgets(numrow, numcol) def makewidgets(self, numrow, numcol): self.rows = [] for i in range(numrow): cols = [] for j in range(numcol): en = tk.Entry(self, relief=tk.RIDGE) en.grid(row=i+1, column=j, sticky=tk.NSEW) en.insert(tk.END, '%d.%d' % (i, j)) cols.append(en) self.rows.append(cols) tk.Button(self, text='Load', command=self.onload).grid(row=11, column=0) tk.Button(self, text='Clear', command=self.onclear).grid(row=11, column=2) tk.Button(self, text='Save', command=self.onsave).grid(row=11, column=1) tk.Button(self, text='Quit', command=root.destroy).grid(row=11, column=9) def onclear(self): for row in self.rows: for en in row: en.delete('0', tk.END) en.insert(tk.END, '0.0') def onload(self): load = filedialog.askopenfilename() if load: with open(load, 'r') as loadfile: filelines = loadfile.readlines() self.numrow = len(filelines) self.numcol = len(filelines[ 0 ].split()) ### Distrugge vecchie entry e ricrea ### for row in self.rows: for en in row: en.destroy() self.makewidgets(self.numrow, self.numcol) ### Scrive nelle entry i dati letti da file ### for row, line in enumerate(filelines): for col, value in enumerate(line.split()): en = self.rows[ row ][ col ] en.delete('0', tk.END) en.insert(tk.END, value) def onsave(self): save = filedialog.asksaveasfilename() if save: check = os.listdir('.') if save in check: os.remove(save) with open(save, 'w') as savefile: for row in self.rows: savefile.write(' '.join(str(en.get()) for en in row)+'\n') if __name__ == '__main__': root = tk.Tk() root.title('Eppendorf') portaeppendorf(root).pack() root.mainloop() *** Il codice va evidenziato con il simbolo di fianco ai colori per non perdere l'indentazione *** |
Pagina: 1
Esegui il login per scrivere una risposta.