2015-08-24 2 views
1

Каков правильный способ реализовать диалог сохранения файлов с пакетом от Enthought? На данный момент у меня есть функция экономии, наблюдающая за изменениями в признаке filename_out (т. Е. File). Неудивительно, что это ничего не делает, когда пользователь хочет сохранить один и тот же файл, переписывая его каждый раз. Как мне сохранить файл каждый раз, когда пользователь подтверждает переписывание в диалоге FileEditor?Python traitsui save файл диалог - переписывание

Небольшой кусочек не-рабочий код:

from traits.api import File, HasTraits 
from traitsui.api import FileEditor, View, Item 
import numpy 

class ArrayToBeSaved(HasTraits): 
    filename_out = File 

    traits_view = View(Item('filename_out', editor = FileEditor(dialog_style='save'))) 

    def __init__(self): 
     self.my_array = numpy.ones(3) 

    #This is NOT the right way 
    def _filename_out_changed(self): 
     numpy.save(self.filename_out, self.my_array) 
     self.my_array = numpy.zeros(3) 

atbs = ArrayToBeSaved() 

atbs.configure_traits() 

После выбора местоположения файла, массив единиц сохраняется. После вызова диалогового окна файла еще раз, выбрав один и тот же файл, пользователю предлагается подтвердить перезапись. Однако ничего не происходит, поскольку filename_out не был изменен.

EDIT: Я хотел бы пояснить, что FileEditor спрашивается подтвердить перезапись, но не спасает файл.

ответ

1

Благодаря aestrivex я могу представить полный ответ. pyface.file_dilaog действительно выполняет эту работу. Поскольку мне потребовалось некоторое время, чтобы выяснить, как его использовать, я решил опубликовать полный рабочий пример.

Это работает также для повторного открытия и тот же файл, только Ставить атрибут FileDialog к action = 'open' (например, если вы случайно изменить значения чего-то и хотите вернуться к насытить, который сохраняется на жестком диске - ситуация, которая также не работает, если вы полагаетесь на наблюдение за изменением признака File.)

from traits.api import HasTraits, Button 
from traitsui.api import View, Item 
import numpy 

##you may need to uncoment these 2 lines to prevent 
##ImportErrors due to missing backends 
#from traits.etsconfig.api import ETSConfig 
#ETSConfig.toolkit = 'qt4' # or 'wx'  

from pyface.api import FileDialog, OK 


class ArrayToBeSaved(HasTraits): 
    save_as = Button('save as') 

    traits_view = View(Item('save_as')) 

    def __init__(self): 
     self.my_array = numpy.ones(3) 

    def _save_as_changed(self): 
     dlg = FileDialog(action='save as') 
     if dlg.open() == OK: 
      numpy.save(dlg.path, self.my_array) 
      self.my_array = numpy.zeros(3) 

atbs = ArrayToBeSaved() 

atbs.configure_traits() 
1

Обратите внимание, что вы можете использовать pyface.file_dialog, который автоматически имеет поведение «вы хотите перезаписать этот файл». Если вам действительно не нужно, чтобы ваше имя было признаком, сделайте это вместо этого, это намного проще.

Если есть хорошая причина для того, чтобы имя файла являлось признаком, вам необходимо продолжить, чтобы возобновить его после проверки ответа пользователя.

Существует много возможных способов сделать это, но вот как мне это нравится. Обратите внимание, что я не тестировал этот код.

import os 
from traits.api import File, HasTraits, Function, Bool, Event 
from traitsui.api import FileEditor, View, Item, Handler, OKCancelButtons, Label 
import numpy 

class CheckOverwriteWindow(Handler): 

    finished = Bool 
    notify = Event 

    def init_info(self, info): 
    self.finished = False 

    def closed(self, info, is_ok): 
    self.finished = is_ok 
    self.notify = True 

    view = View(
    Label('Really overwrite?'), 
    buttons = OKCancelButtons 
) 

class ArrayToBeSaved(HasTraits): 
    filename_out = File 
    _save_continuation = Function 
    _check_overwrite_window = Instance(CheckOverwriteWindow,()) 

    traits_view = View(Item('filename_out', editor = FileEditor(dialog_style='save'))) 

    def __init__(self): 
     self.my_array = numpy.ones(3) 

    def _filename_out_changed(self): 
     def save_continuation(): 
      numpy.save(self.filename_out, self.my_array) 
      self.my_array = numpy.zeros(3) 
     if not os.path.exists(self.filename_out): 
      save_continuation() 
     else: 
      self._save_continuation = save_continuation 
      self._check_overwrite_window.edit_traits() 

    @on_trait_change('_check_overwrite_window:notify') 
    def handle_overwrite(self): 
     if self._check_overwrite_window.finished: 
      self._save_continuation() 

atbs = ArrayToBeSaved() 

atbs.configure_traits() 
+0

Спасибо за ответ! Тем не менее, я все еще что-то пропущу. После добавления импорта 'Instance' и' on_trait_change' я столкнулся с такой же проблемой: выбор одного и того же имени дважды приводит к отсутствию действия, хотя диалог файла запрашивает подтверждение. Ваш код работает, когда вы выбираете 'name1.npy', затем' name2.npy', а затем снова 'name1.npy', но так же и мой. Это добавляет еще один этап подтверждения. –

+0

Извините, я не понял ваш вопрос правильно, но также не думаю, что вы четко определили свою конкретную проблему. Если вы используете редактор по умолчанию для выбора файла, он не обновит признак, если файл фактически не изменился. Вернее, он обновит этот признак, но поскольку значение не изменится, это не приведет к запуску уведомления. У вас будет более легкое время делать то, что вы хотите, написав обертку вокруг «pyface.FileDialog» (я упомянул в начале моего ответа). Эта оболочка всегда может вернуть значение, тогда как 'FileEditor' ничего не вызовет, если черта не изменится. – aestrivex