Python traitsui保存文件对话 - 覆盖

时间:2015-08-24 09:17:29

标签: python save traits traitsui

使用来自Enthought的traitsui包实现文件保存对话的正确方法是什么?目前,我有实际的保存功能,可以观察特征filename_out(即File特征)的变化。不出所料,当用户想要反复保存到同一个文件,每次都覆盖它时,这没有任何作用。每次用户确认在FileEditor对话框中确认覆盖时,如何保存文件?

一小段无法工作的代码:

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()

选择文件位置后,将保存1的数组。再次调用文件对话框后,选择相同的文件,要求用户确认覆盖。但是,没有任何反应,因为filename_out没有改变。

编辑:我想说清楚,FileEditor 确实要求确认覆盖,但不保存该文件。

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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()