2015-08-24 66 views
1

什麼是正確的方式來與Enthought的traitsui包實現文件保存對話?目前,我有實際的儲蓄功能來觀察特徵filename_out(即File特徵)的變化。毫不奇怪,當用戶想要重複保存到同一個文件時,它不會做任何事情,每次都會覆蓋它。每次用戶在FileEditor對話框中確認覆蓋時,如何讓它保存文件?Python traitsui保存文件對話框 - 覆蓋

一小片的未工作的代碼:

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沒有改變。

編輯:我想弄清楚,那FileEditor 不問確認覆蓋,但不保存文件。

回答

1

感謝aestrivex我可以提出一個完整的答案。 pyface.file_dilaog確實做這份工作。由於花了我一些時間才弄清楚如何使用它,我決定發佈一個完整的工作示例。

這工作也重新打開相同的文件,只恰克的FileDialogaction = '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