Python traitsui 保存文件对话-覆盖

Python traitsui save file dialogue - overwriting

使用 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 确实要求确认覆盖,但不保存文件。

请注意,您可以使用 pyface.file_dialog,它会自动具有 "do you want to overwrite this file" 行为。如果您实际上不需要将文件名作为特征,那么这样做会简单得多。

如果有充分的理由将文件名作为特征,则需要在检查用户的响应后继续继续。

有很多可能的方法,但这是我喜欢的方法。请注意,我没有测试此代码。

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

感谢 aestrivex,我可以提供完整的答案。 pyface.file_dilaog 真的很管用。由于我花了一些时间来弄清楚如何使用它,所以我决定 post 一个完整的工作示例。

这也适用于重新打开同一个文件,只需将 FileDialog 的属性更改为 action = 'open'(例如,如果您不小心编辑了某些内容的值并希望 return到保存在您磁盘上的状态 - 如果您依赖于观察 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()