Saving & restoring the state of a complex GUI

259 views
Skip to first unread message

cappy2112

unread,
Nov 9, 2009, 1:48:45 PM11/9/09
to wxPython-users

I've written a few simple wx & pythoncard-based Gui's.

I am now starting on a program with a wx-based GUI, will be quite
more complex than the others.
Complex- in the sense it will probably have 6-10 tabs, each with many
(30+ ??) widgets or so.

The users of this GUI have expressed the ability to save the state of
the GUI once all of the information has been loaded into the widgets
(mostly text boxes).

Initially I had thought of pickling the entire Window to disk, passing
the outermost Frame as the object to pass to the pickle function, then
doing the reverse when un-pickling. This seems like a better way than
iterating over all of the widgets, and manually saving their contents.

I don't know if this will work with a GUI and I'm curious how others
would go about this.
It's quite possible wx already has an API do do this. Is this the
case?


Thanks

Mike Driscoll

unread,
Nov 9, 2009, 2:56:29 PM11/9/09
to wxPython-users
Hi,
Due to the SWIG interface between Python and wx, the ability to pickle
some of the wx objects becomes problematic. If they're just filling
out a form, I'd save the data to a database and open the last record
when the program is opened. Python 2.5+ includes SQLite.

There's a new AUI in the agw set that allows you to save
"perspectives", which I think means you can save the sizes of the
notebooks and panes. I'm not sure if that includes the data too
though.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

Paul McNett

unread,
Nov 9, 2009, 3:30:08 PM11/9/09
to wxpytho...@googlegroups.com
Mike Driscoll wrote:
> Hi,
>
> On Nov 9, 12:48 pm, cappy2112 <cappy2...@gmail.com> wrote:
>> I've written a few simple wx & pythoncard-based Gui's.
>>
>> I am now starting on a program with a wx-based GUI, will be quite
>> more complex than the others.
>> Complex- in the sense it will probably have 6-10 tabs, each with many
>> (30+ ??) widgets or so.
>>
>> The users of this GUI have expressed the ability to save the state of
>> the GUI once all of the information has been loaded into the widgets
>> (mostly text boxes).
>>
>> Initially I had thought of pickling the entire Window to disk, passing
>> the outermost Frame as the object to pass to the pickle function, then
>> doing the reverse when un-pickling. This seems like a better way than
>> iterating over all of the widgets, and manually saving their contents.
>>
>> I don't know if this will work with a GUI and I'm curious how others
>> would go about this.
>> It's quite possible wx already has an API do do this. Is this the
>> case?
>>
>
> Due to the SWIG interface between Python and wx, the ability to pickle
> some of the wx objects becomes problematic. If they're just filling
> out a form, I'd save the data to a database and open the last record
> when the program is opened. Python 2.5+ includes SQLite.
>
> There's a new AUI in the agw set that allows you to save
> "perspectives", which I think means you can save the sizes of the
> notebooks and panes. I'm not sure if that includes the data too
> though.

This definitely calls for a database. You are wanting to save and restore data, so
use a database. Use SQLite as Mike mentioned.

Consider using Dabo, which comes with some out-of-the-box solutions, one of which is
the relatively heavy db/biz/ui interaction where you define a connection, define a
bizobj with your business rules, and then define your ui to get/set the data from/to
the bizobj. You do this using the DataSource and DataField properties of the UI
controls. Once set up, Dabo does the rest.

The other Dabo alternative, if this really isn't a database app but you still want
the form to come up pre-populated with the last values, is to let Dabo save the
values for you to the daboPreferences.db file (a sqlite database persisted to the
user's %appdata% directory). Just set SaveRestoreValue to True for the controls you
want to persist like this, and when you open the form all those values will be
prepopulated, and when you close the form the current values will be persisted. No
other code needed, although you can explicitly call saveValue() whenever you want.

Paul

Stef Mientki

unread,
Nov 9, 2009, 3:39:50 PM11/9/09
to wxpytho...@googlegroups.com
cappy2112 wrote:
> I've written a few simple wx & pythoncard-based Gui's.
>
> I am now starting on a program with a wx-based GUI, will be quite
> more complex than the others.
> Complex- in the sense it will probably have 6-10 tabs, each with many
> (30+ ??) widgets or so.
>
> The users of this GUI have expressed the ability to save the state of
> the GUI once all of the information has been loaded into the widgets
> (mostly text boxes).
>
For these kind of "complex" visual designs,
I created GUI_support, which not only saves and stores but also gives
you a quit easy way of designing the GUI
http://mientki.ruhosting.nl/data_www/pylab_works/pw_gui_support.html
I've you're interested, I can load up the latest version.
cheers,
Stef

Andrea Gavana

unread,
Nov 9, 2009, 4:09:16 PM11/9/09
to wxpytho...@googlegroups.com
Hi,

2009/11/9 cappy2112:

Other than the solutions Stef and Paul proposed (I like the Dabo one,
although I am no fan of Dabo in general), it would be nice to have
some kind of mixin (let's call it PersistentControlsMixin) that allows
you to save and restore GUI components values/sizes/whatever else.
Pretty much like the wxWidgets' one on which Vadim Zeitlin was working
on, although I believe it has not been finished (and possibly it has
been discontinued).

One day or the other I may end up writing something like this to have
a wxPython-pluggable mixin ready to use and independent from 3rd party
libraries (no offence anyone).

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
http://thedoomedcity.blogspot.com/

Mike Driscoll

unread,
Nov 10, 2009, 9:19:07 AM11/10/09
to cappy2112, wxpytho...@googlegroups.com
Hi,

On Mon, Nov 9, 2009 at 2:23 PM, cappy2112 <capp...@gmail.com> wrote:
> Thanks Mike
>
> Do you have any other alternatives to using a db?
> I've got tons of work to do with the gui, and I'd say I'm a bit passed
> the beginners stage with wx, but not at intermed level.
> I've also got to parse three different files of symbolic data from a C
> compiler, and get that into a viewable form in the gui.
> I know 0 about db technology, and the thought of having to learn it at
> this point just doesn't seem like the best approach as far as time is
> concerned.
>


Learning how to insert and update SQLite is very easy. Just look at the docs:

http://docs.python.org/library/sqlite3.html

Of course, if all you care about is the current data being worked on,
then you could just iterate over the widgets and create a list that
you could pickle or you could save it all to some kind of file. I've
been using ConfigParser and ConfigObj to store user preferences, but
you could use them to store the data too. I think ConfigObj is the
more flexible of the two.

Here's a couple of links:

http://docs.python.org/library/configparser.html
www.voidspace.org.uk/python/configobj.html

Robin Dunn

unread,
Nov 10, 2009, 4:55:19 PM11/10/09
to wxpytho...@googlegroups.com
On 11/9/09 1:09 PM, Andrea Gavana wrote:

> One day or the other I may end up writing something like this to have
> a wxPython-pluggable mixin ready to use and independent from 3rd party
> libraries (no offence anyone).

When you're ready to do this let me know. I wrote a little settings
saving framework in one of the projects I've worked on, which also
allows different targets for where the settings are actually stored. It
may be able to be extracted from the project it is in now and could
serve as a starting point for you.

--
Robin Dunn
Software Craftsman
http://wxPython.org

Andrea Gavana

unread,
Nov 10, 2009, 5:58:25 PM11/10/09
to wxpytho...@googlegroups.com
Hi Robin,

2009/11/10 Robin Dunn:

I am already half-way or more with this thing: I took a couple of
hours today to do it and it is surprisingly simple with Python. In any
case, I had thought about different targets myself too and this
feature is already incorporated in the project. I am currently
creating saving/restoring features for
treectrls/CustomTreeCtrl/HyperTreeList/etc (I am going in alphabetic
order and I already reached the "T" letter :-D ).
It should be ready in few days, then we might see if I interpreted
correctly your sentence about "different targets".

skip.mo...@gmail.com

unread,
Nov 10, 2009, 11:19:29 PM11/10/09
to wxpytho...@googlegroups.com
I wrote a widget saver for PyGTK a couple years ago. It was quite easy
given the ability to connect to the various signals GTK widgets emit. You
just save the state of the widgets and when the program exits you pickle the
result. Next time you start your app the pickled data are used to
(re)initialize the widgets.

I don't know wx well enough to know if such a scheme will work there or not.
The PyGTK version is less than 250 lines of code. If it would be of
interest I'll check at work to see if I can release it.

--
Skip Montanaro - sk...@pobox.com - http://www.smontanaro.net/

Andrea Gavana

unread,
Nov 11, 2009, 11:44:51 AM11/11/09
to wxpytho...@googlegroups.com
Hi Skip,

2009/11/11 <skip.mo...@gmail.com>:


>
> I wrote a widget saver for PyGTK a couple years ago.  It was quite easy
> given the ability to connect to the various signals GTK widgets emit.  You
> just save the state of the widgets and when the program exits you pickle the
> result.  Next time you start your app the pickled data are used to
> (re)initialize the widgets.
>
> I don't know wx well enough to know if such a scheme will work there or not.
> The PyGTK version is less than 250 lines of code.  If it would be of
> interest I'll check at work to see if I can release it.

It would be interesting to see the approach you used: I am pretty much
finished wrapping all the possible widgets in wxPython and I got close
to 2,000 lines of code :-D. I simply followed the wxWidgets
implementation (which currently supports 4 widgets only) by having a
central and unique PersistenceManager and delegate all the
saving/restoring to appropriate classes depending on the widget type.

In any case, I believe that having 2 implementations of the same
feature will only be beneficial to wxPython :-D

Paul McNett

unread,
Nov 12, 2009, 9:34:57 AM11/12/09
to wxpytho...@googlegroups.com
Andrea Gavana wrote:
> It would be interesting to see the approach you used: I am pretty much
> finished wrapping all the possible widgets in wxPython and I got close
> to 2,000 lines of code :-D. I simply followed the wxWidgets
> implementation (which currently supports 4 widgets only) by having a
> central and unique PersistenceManager and delegate all the
> saving/restoring to appropriate classes depending on the widget type.

What's the use-case for persisting every little thing about a widget instance? I can
only see a use for persisting a few specific things:

1) The value of a widget, like the text in a TextCtrl or the selection index in a list.

2) The window state (maximized, minimized, etc.), the window size, and the window
position, but only for top-level windows.

3) Other control-specific things such as the current sash position and the column
order in a grid.

In other words, you persist things that the *user* changed.

Paul

Andrea Gavana

unread,
Nov 12, 2009, 9:44:57 AM11/12/09
to wxpytho...@googlegroups.com
Hi,

2009/11/12 Paul McNett:

I pretty much knew that already, no need for a lesson. Persistent
object save and restore only attributes that the user can change, not
the ones the programmer input. This is the same philosophy the
wxWidgets Persistent Objects follow.

Paul McNett

unread,
Nov 12, 2009, 12:55:52 PM11/12/09
to wxpytho...@googlegroups.com
Andrea Gavana wrote:
> Hi,
>
> 2009/11/12 Paul McNett:
>> Andrea Gavana wrote:
>>> It would be interesting to see the approach you used: I am pretty much
>>> finished wrapping all the possible widgets in wxPython and I got close
>>> to 2,000 lines of code :-D. I simply followed the wxWidgets
>>> implementation (which currently supports 4 widgets only) by having a
>>> central and unique PersistenceManager and delegate all the
>>> saving/restoring to appropriate classes depending on the widget type.
>> What's the use-case for persisting every little thing about a widget instance? I can
>> only see a use for persisting a few specific things:
>>
>> 1) The value of a widget, like the text in a TextCtrl or the selection index in a list.
>>
>> 2) The window state (maximized, minimized, etc.), the window size, and the window
>> position, but only for top-level windows.
>>
>> 3) Other control-specific things such as the current sash position and the column
>> order in a grid.
>>
>> In other words, you persist things that the *user* changed.
>
> I pretty much knew that already, no need for a lesson. Persistent
> object save and restore only attributes that the user can change, not
> the ones the programmer input. This is the same philosophy the
> wxWidgets Persistent Objects follow.

Oh I misunderstood you then. My apologies! You said "all possible widgets" and "~2000
lines of code" which made me wonder.

Cheers!
Paul

Andrea Gavana

unread,
Nov 12, 2009, 7:18:24 PM11/12/09
to wxpytho...@googlegroups.com
I really want to believe you are not being ironic with your message.

2009/11/12, Paul McNett <p...@ulmcnett.com>:
--

Paul McNett

unread,
Nov 12, 2009, 8:28:20 PM11/12/09
to wxpytho...@googlegroups.com
Andrea Gavana wrote:
> I really want to believe you are not being ironic with your message.

I simply started from a bad assumption (that you were saving every detail about the
instance). So, I misuderstood, and I apologized. No (intended) irony at all.

Paul

cappy2112

unread,
Nov 18, 2009, 5:31:30 PM11/18/09
to wxPython-users


> What's the use-case for persisting every little thing about a widget instance? I can
> only see a use for persisting a few specific things:

With a GUI that has many widgets filled with lots of information,
saving the exact state of the gui so it can be restored
without the user having to perform all of the same actions to get the
same info on the screen.

Paul McNett

unread,
Nov 18, 2009, 5:46:12 PM11/18/09
to wxpytho...@googlegroups.com

Right, but how many ways can a user change a given widget?

The frame:
size
position
state (maximized, minimized, ...)

A text ctrl:
value

etc.

Andrea already corrected my false assumption that things like font would be persisted
(because ostensibly if the user was changing something like this, they'd be using a
widget somewhere to do this, and *that* widget would persist its value).

Paul

Robin Dunn

unread,
Nov 19, 2009, 9:30:14 PM11/19/09
to wxpytho...@googlegroups.com

I'd argue that those kinds of things belong in the application's data
model and not in the widget persistence data. The things that should go
there are things like frame size and position, splitter window sash
position, etc. If you're mixing all that with the values in the widgets
then you'll certainly run into problems somewhere along the line unless
it's a very simple app.

Andrea Gavana

unread,
Nov 20, 2009, 2:56:17 AM11/20/09
to wxpytho...@googlegroups.com
2009/11/20 Robin Dunn:

It depends on what you are actually saving and restoring. Saving and
restoring a textctrl value or a treectrl expansion state makes sense
to me as a "persistent" attribute. The only 2 reasons why the code in
PersistentControls ended up being longer than I expected are:

1) Lots of documentation;
2) The API inconsistency between widgets that should be very similar
(i.e. wx.TreeCtrl, wx.lib.agw.CustomTreeCtrl, wx.gizmos.TreeListCtrl
and wx.lib.agw.HyperTreelist, not to mention the nightmare of the
various wx.ListCtrl, wx.ListBox, wx.VListBox, wx.HtmlListBox and so
on).

Other than that, I don't think there was much interest in
PersistentControls in the end. I haven't received a single feedback
(not even a bad one, which is not a good sign :-D ).

Karsten Hilbert

unread,
Nov 20, 2009, 6:25:56 AM11/20/09
to wxpytho...@googlegroups.com
> >> What's the use-case for persisting every little thing about a widget
> instance? I can
> >> only see a use for persisting a few specific things:
> >
> > With a GUI that has many widgets filled with lots of information,
> > saving the exact state of the gui so it can be restored
> > without the user having to perform all of the same actions to get the
> > same info on the screen.
>
> I'd argue that those kinds of things belong in the application's data
> model and not in the widget persistence data. The things that should go
> there are things like frame size and position, splitter window sash
> position, etc.

... list ctrl column sizes, grid ctrl cell attributes, dialog sizes ...

Yes, I agree !

Karsten
--
GRATIS für alle GMX-Mitglieder: Die maxdome Movie-FLAT!
Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome01

Mike Driscoll

unread,
Nov 20, 2009, 10:27:23 AM11/20/09
to wxPython-users
Hi Andrea,
Don't give up! I'm just not sure how I would use it right now as I
don't really persist anything in my current programs (beyond some user
settings in an INI file).

I thought I saw someone reply to your announcement that they would be
checking it out this week.

C M

unread,
Nov 20, 2009, 11:15:06 AM11/20/09
to wxpytho...@googlegroups.com

Yes, I'd second Mike's point. I was intrigued by PersistentControls
and intend to check it out at some point soon, but wanted to fix some
other problems I have been struggling with first. I'm also unsure whether
or not it would be helpful for what I am hoping to do--it very well might be,
I will just need a chance to play with it and see. I have been trying to
figure out how to have sort of "optional panels", in which each panel
would be a different set of widgets, but the user can sub in or out the
ones s/he'd want, or even create custom panels...and so I thought
maybe PersistentControls could be useful for that. I'll look into it.

But again, the rapidity and frequency with which you bring new value to
wxPython is pretty astonishing, and although few have commented on
it, I'd be surprised if most weren't pleased that it is made available as
an option. I certainly continue to appreciate all these new controls! :D

Che

Skip Montanaro

unread,
Nov 20, 2009, 1:49:06 PM11/20/09
to wxpytho...@googlegroups.com
> I'd argue that those kinds of things belong in the application's data
> model and not in the widget persistence data.  The things that should go
> there are things like frame size and position, splitter window sash
> position, etc.

The user's desired default values might not represent the current
state of the model. I know this is a fuzzy thing, but if, for example, I
have some sort of auction bidding app which presents me with a bid
increment, what might actually be represented in the model is the
last price I bid. The bid increment is just a convenience. (Though I
will agree that you could convincingly argue that the bid increment
is a piece of model data. The bid increment for a rare coin might
be different than the bid increment for a rare car.)

Skip

Olemis Lang

unread,
Nov 20, 2009, 1:59:36 PM11/20/09
to wxpytho...@googlegroups.com
On Fri, Nov 20, 2009 at 2:56 AM, Andrea Gavana <andrea...@gmail.com> wrote:
>
> Other than that, I don't think there was much interest in
> PersistentControls in the end. I haven't received a single feedback
> (not even a bad one, which is not a good sign :-D ).
>

/me silently likes it

> "Imagination Is The Only Weapon In The War Against Reality."

/me using my imagination

:P

--
Regards,

Olemis.

Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/

Featured article:

Olemis Lang

unread,
Nov 20, 2009, 2:10:44 PM11/20/09
to wxpytho...@googlegroups.com

IMO , I like Borland Delphi's approach :

- Save everything that might be needed (and can be saved).
In that case that means values of published properties.
- Make it work even with non-visual objects (e,g, cell attributes
in grid table models)

It's fast as hell !

PS: I know things are different in wxPy-land

Paul McNett

unread,
Nov 20, 2009, 4:58:11 PM11/20/09
to wxpytho...@googlegroups.com

IOW, save the Value of the text box where the user specifies the default increment
for automobiles versus coins. Saving/restoring the Value of a textbox can be a
widget-level thing, but saving/restoring the bid increment for coins versus autos is
very much an application-specific thing.

If the persistence mixin could also be used independently, then app-specific things
could be saved to the same database, alongside widget values. Indeed, this is what
Dabo does: there's dApp.get|setUserSetting methods, and these very methods are what
get called by the widgets when saving/restoring window size, positions, textbox
values, etc.

Paul

cappy2112

unread,
Nov 30, 2009, 1:37:54 PM11/30/09
to wxPython-users

> Due to the SWIG interface between Python and wx, the ability to pickle
> some of the wx objects becomes problematic.
> -------------------
> Mike Driscoll

Mike-

I did try this just to see what would happen, and I did get an
exception related to a swig object.
Is this something unique to pickling, or would you expect the same to
occur with marshal & shelve?

When I tried pickling, I passed the upper most Window handle, did not
try picking textboxes or other single widgets.

Mike Driscoll

unread,
Nov 30, 2009, 2:10:29 PM11/30/09
to wxPython-users
Robin is more qualified to answer this than I am. I'm pretty sure that
shelving will give a similar error, but I've never tried it.

See the following thread for an old Robin answer on this topic:

http://old.nabble.com/How-to-pickle-a-%27PySwigObject%27---td23708271.html

You might give Andrea's new Perspectives saving script a try. It may
overcome this issue or at least give you some ideas.

Olemis Lang

unread,
Nov 30, 2009, 2:19:38 PM11/30/09
to wxpytho...@googlegroups.com
On Mon, Nov 30, 2009 at 1:37 PM, cappy2112 <capp...@gmail.com> wrote:
>
>> Due to the SWIG interface between Python and wx, the ability to pickle
>> some of the wx objects becomes problematic.
>> -------------------
>> Mike Driscoll
>
> Mike-
>
> I did try this just to see what would happen, and I did get an
> exception related to a swig object.
> Is this something unique to pickling, or would you expect the same to
> occur with marshal &

don't know.

> shelve?
>

Shelve relies on pickle too

> When I tried pickling, I passed the upper most Window handle,  did not
> try picking textboxes or other single widgets.
>

--
Regards,

Olemis.

Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/

Featured article:
Looking for a technique to create flexible, graphical dashboards ...
- http://feedproxy.google.com/~r/TracGViz-full/~3/YfBiyx_E6jM/0298ec51c9e9bae2

Robin Dunn

unread,
Nov 30, 2009, 3:59:28 PM11/30/09
to wxpytho...@googlegroups.com
On 11/30/09 10:37 AM, cappy2112 wrote:
>
>> Due to the SWIG interface between Python and wx, the ability to pickle
>> some of the wx objects becomes problematic.
>> -------------------
>> Mike Driscoll
>
> Mike-
>
> I did try this just to see what would happen, and I did get an
> exception related to a swig object.
> Is this something unique to pickling, or would you expect the same to
> occur with marshal& shelve?

The swig object contains a pointer to the C++ object someplace in
memory. Python has no idea what this pointer means nor what is the
structure of what it is pointing to, so there is no way for it to
serialize a copy of that data to a stream of bytes.

If you have a class derived from a wx class that you really want to be
picklable, then what I suggest is to simply separate the UI object from
the parts that need to be saved and restored, and pickle that instead.
Also look up __reduce__ in the pickle documentation and how implementing
it in a class can help out the process.
Reply all
Reply to author
Forward
0 new messages