2015-04-07 19 views
5

Sto provando a creare una finestra di dialogo di salvataggio in tkinter. Ho bisogno di salvare il nome del file da usare in seguito. Tuttavia, non voglio che il filedialog accetti di selezionare un nome di file già esistente.salva come finestra di dialogo - come non consentire la sovrascrittura

Finora ho solo questo:

from tkinter import filedialog 

my_file = filedialog.asksaveasfilename(defaultextension = ".myfile", 
             filetypes = [("MY SUPER FILE", ".myfile"), 
                ("All files", ".*")]) 

Una possibilità potrebbe essere quella di ottenere il nome del file, controllare se esiste (utilizzando os.path.isfile) e chiedo di nuovo l'utente per il nuovo nome se esiste già un file con lo stesso nome Tuttavia, il filedialog di tkinter chiede all'utente "il file esiste già. Vuoi sovrascrivere?". Quindi sembra confondersi se in seguito dico all'utente che non accetto la scelta del nome file. C'è un modo per forzare il filedialog di tkinter a non chiedere all'utente la sovrascrittura?

Modifica: Sulla base dei suggerimenti nelle risposte, ho provato a creare la mia finestra di dialogo di salvataggio.

ho praticamente solo aggiunto un avvertimento per il Tkinter finestra di salvataggio:

class MySaveFileDialog(filedialog.FileDialog): 

""" File save dialog that does not allow overwriting of existing file""" 
def ok_command(self): 
    file = self.get_selection() 
    if os.path.exists(file): 
     if os.path.isdir(file): 
      self.master.bell() 
      return 
     messagebox.showarning("The current file name already exists. Please give another name to save your file.") 
    else: 
     head, tail = os.path.split(file) 
     if not os.path.isdir(head): 
      self.master.bell() 
      return 
    self.quit(file) 

Così, sembra piuttosto semplice. Poi ho pensato: ho bisogno di creare la mia funzione asksaveasfilename. sono andato a controllare la fonte:

def asksaveasfilename(**options): 
"Ask for a filename to save as" 

return SaveAs(**options).show() 

Humm .. Ho bisogno di vedere ciò che è SaveAs facendo.

class SaveAs(_Dialog): 
    "Ask for a filename to save as" 

    command = "tk_getSaveFile" 

Aaanndd ... sono perso. Non capisco come si integrino questi pezzi. 'SaveAs' ha solo il comando tk_getSaveFile. Come si usa SaveFileDialog qui? E come posso creare la mia funzione myasksaveasfilename?

+1

Do you _really_ serve questo? Le finestre di dialogo con comportamento non standard confondono l'utente. Inoltre, se l'utente vuole sovrascrivere un file esistente, è bene avvisarlo, ma è davvero fastidioso fermarlo. Quindi, se il nome selezionato corrisponde a un file esistente, è possibile aprire una finestra di messaggio 'askokcancel' per dare loro un'ultima possibilità prima di spararsi nel piede.:) –

+0

@PM 2Ring: capisco la tua preoccupazione. E mi piacerebbe non farlo in questo modo, ma ne ho davvero bisogno :) – zelite

+0

Due cose che contano in tale problema: 1) l'utente ha un altro mezzo per farlo? 2) sarà usato volontariamente più spesso che come errore? Qui 1) la risposta è sì (è possibile eliminare il file all'esterno dell'app) e 2) la risposta dipende da cosa fa l'app. –

risposta

5

Non esiste questa opzione. Se vuoi eliminare la domanda di sicurezza, dovrai scrivere la tua finestra di dialogo.

Se si guarda filedialog.py, si vedrà che la finestra di dialogo è implementata in Python. Quindi tutto ciò che dovete fare è estendere la classe SaveFileDialog e sovrascrivere il metodo ok_command() con uno che non consente di selezionare un nome di file esistente.

È possibile utilizzare la maggior parte del codice esistente e modificare solo alcuni testi per raggiungere il proprio obiettivo.

non ho ancora testato, ma questo codice dovrebbe funzionare:

def ok_command(self): 
     file = self.get_selection() 
     if os.path.exists(file): 
      if os.path.isdir(file): 
       self.master.bell() 
       return 
      d = Dialog(self.top, 
         title="Overwrite Existing File", 
         text="You can't overwrite an existing file %r. Please select a new name." % (file,), 
         bitmap='error', 
         default=0, 
         strings=("OK",)) 
      return 
     else: 
      head, tail = os.path.split(file) 
      if not os.path.isdir(head): 
       self.master.bell() 
       return 
     self.quit(file) 
+0

Grazie per avermi indicato nella giusta direzione. – zelite

+0

Nota: la finestra di dialogo del file è implementata in python su sistemi Linux. Su Windows e OSX è una finestra di dialogo dei file nativi. –

+0

@BryanOakley Si potrebbe fare una classe ereditando da 'FileDialog.SaveFileDialog', sovrascrivere il' ok_command' e chiamarlo usando 'fd = MySaveFileDialog (root)' 'filename = fd.go()' sebbene sia giusto? Anche se, naturalmente, questo non sembra altrettanto bello della finestra di dialogo del sistema operativo nativo. – fhdrsdg

0

per completare quello che ha detto Aaron, ecco il codice attuale del ok_command:

def ok_command(self): 
     file = self.get_selection() 
     if os.path.exists(file): 
      if os.path.isdir(file): 
       self.master.bell() 
       return 
      d = Dialog(self.top, 
         title="Overwrite Existing File Question", 
         text="Overwrite existing file %r?" % (file,), 
         bitmap='questhead', 
         default=1, 
         strings=("Yes", "Cancel")) 
      if d.num != 0: 
       return 
     else: 
      head, tail = os.path.split(file) 
      if not os.path.isdir(head): 
       self.master.bell() 
       return 
     self.quit(file) 
0

È possibile ottenere ciò utilizzando tkFileDialog.asksaveasfilename(confirmoverwrite=False)
Ecco un mock up:

import tkFileDialog 
import tkMessageBox as mbox 
class Example(): 
    proceed = False 
    while proceed == False: 
     dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False) 
     fname = dlg 
     if fname != '': 
      try: 
       f = open(fname, "r") 
       f.close() 
       mbox.showerror("Error","File exists - Choose another file name") 
      except: 
       mbox.showinfo("Info","File does not exist - Continue") 
       proceed = True 
     else: 
      break 
    print("Finished") 
Problemi correlati