【问题标题】:Unable to save persistence file using wxPython PersistenceManager无法使用 wxPython PersistenceManager 保存持久性文件
【发布时间】:2017-06-20 15:05:12
【问题描述】:

我正在使用 wxpython 开发一个 GUI 应用程序,它有大约 110 个用户选择的参数。因为我希望用户能够将这些选项保存到项目文件中,所以我决定使用 wxPython 中包含的 PersistenceManager 模块。

只要我不尝试指定保存设置的文件名,即我使用默认值 (C:\users\username\AppData\programName\Persistence_Options),并且让程序在退出时保存设置,持久性就可以很好地工作.

我想要做的是允许用户选择一个文件来保存设置(因为他们可能有多个具有不同选项的项目)。但是,当我将SetPersistenceFile 方法与用户指定的文件名一起使用时,没有文件被保存,也没有返回错误消息,即使它确实在执行下面给出的那些代码行。 (OnSave函数是程序主窗口的方法。)

def OnSave(self, e):
    self.dirname = os.getcwd()
    if self.ProjectFile == '':
        dlg = wx.FileDialog(self, "Save project file", self.dirname, "", "Project configuration file (.prj)|*.prj", wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_CANCEL:
            return
        else:
            self.ProjectFile = os.path.join(dlg.GetDirectory(), dlg.GetFilename())
            #print self.ProjectFile

    if self.ProjectFile != '':
        print "Made it to here (Save)..."
        #self.Register(self) # Also tried calling Register in __init__
        self._persistMgr = PM.PersistenceManager.Get()
        print self.ProjectFile # Gives correct filename
        self._persistMgr.SetPersistenceFile(self.ProjectFile)
        self._persistMgr.Save(self)
        print "Finished saving."

我尝试使用本地 PersistenceManager 对象,而不是将其作为类成员,这没有任何区别。有趣的是,如果我在窗口的__init__ 函数中声明self.__persistMgr 对象并在那里使用带有硬编码文件名的SetPersistenceFile 方法,它会写入文件,但是这没有帮助,因为用户需要指定在运行时。

有谁知道为什么文件没有保存以及如何解决这个问题?

【问题讨论】:

    标签: python-2.7 wxpython


    【解决方案1】:

    不确定为什么您的代码让您感到痛苦,以下代码在 Linux 上有效,尽管这可能对您没有任何安慰。
    它是从多个来源拼凑而成的,我自己没有遇到过PersistenceManager

    #!/usr/bin/python
    import wx , os
    import wx.lib.agw.persist as PM
    
    class persist(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent, -1, "A window that maintains size and position after restart")
            self.Bind(wx.EVT_CLOSE, self.OnClose)
    
            # Very important step!!
            if self.GetName() == "frame":
                self.SetName("My Persist Frame") # Do not use the default name!!
    
            dirname = os.getcwd()
            dlg = wx.FileDialog(self, "Project file", dirname, "", "Project configuration file (.prj)|*.prj|All files (*.*)|*.*", wx.FD_SAVE)
            if dlg.ShowModal() == wx.ID_CANCEL:
                _configFile = os.path.join(os.getcwd(), "persist-saved.prj")    # getname()
            else:
                _configFile = os.path.join(dlg.GetDirectory(), dlg.GetFilename())
            print _configFile
            self._persistMgr = PM.PersistenceManager.Get()
            self._persistMgr.SetPersistenceFile(_configFile)
            self._persistMgr.RegisterAndRestoreAll(self)
            self._persistMgr.Save(self)
    
        def OnClose(self, event):
            self._persistMgr.SaveAndUnregister()
            event.Skip()
    
    if __name__ == '__main__':
        my_app = wx.App()
        p = persist(None)
        p.Show()
        my_app.MainLoop()
    

    我的 .prj 文件中的结果:

    [Persistence_Options]
    [Persistence_Options/Window]
    [Persistence_Options/Window/My\ Persist\ Frame]
    x=('int', '9')
    y=('int', '134')
    w=('int', '319')
    h=('int', '78')
    Maximized=('bool', 'False')
    Iconized=('bool', 'False')
    

    注意name 的设置,无论您为持久性保存的是什么,这都是正确的。

    编辑:关于您的评论 我认为您可能希望得到的不仅仅是 PersistenceManager 目前所能应付的。

    wxWidgets 内置了对(不断增长的)数量的控件的支持。目前支持以下类:

    wxTopLevelWindow(以及 wxFrame 和 wxDialog) wxBookCtrlBase(即 wxNotebook、wxListbook、wxToolbook 和 wxChoicebook) wxTreebook 要自动保存和恢复上面列出的类窗口的属性,您需要:

    使用 wxWindow::SetName() 为窗口设置一个唯一的名称:这一步很重要,因为名称在配置文件中使用,因此在同一类的所有窗口中必须是唯一的。 在创建窗口后的任何时候调用 wxPersistenceManager::Register() ,然后在设置可以恢复时调用 wxPersistenceManager::Restore() (不能总是立即完成,例如通常需要先填充窗口)。如果设置可以在窗口创建后立即恢复,例如 wxTopLevelWindow 的情况,那么 wxPersistenceManager::RegisterAndRestore() 可以同时完成这两项工作。 如果您不想保存窗口的设置(例如,如果对话框被取消,对话框大小的更改通常不会保存),您需要手动调用 wxPersistenceManager::Unregister()。否则,当控件本身被销毁时,设置将自动保存。
    来源:http://www.ccp4.ac.uk/dist/checkout/wxPython-src-3.0.2.0/docs/doxygen/out/html/overview_persistence.html

    当然,我可能完全错了,正如我已经承认的那样,我以前没有使用过它,也没有真正研究过它。

    【讨论】:

    • 感谢您的浏览。这个例子工作得很好,但是如果你把它放在一个单独的函数中(就像我试图做的那样),它似乎只捕获框架属性而不是子命名控件。如果您将它留在原来的位置,则子控件会正确保存。
    • 添加了对我原始答案的引用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2013-09-02
    • 2011-05-30
    • 2017-09-15
    相关资源
    最近更新 更多