Reputation: 59408
I want to know when a frame has been resized, so I can save the size and remember it the next time the application launches. Here is my on_resize
method:
def on_resize(self, event):
logic.config_set('main_frame_size',
(event.Size.width, event.Size.height))
event.Skip()
And it's bound like this:
self.Bind(wx.EVT_SIZE, self.on_resize)
The problem is performance. For safety, my logic module saves the config file every time a setting changes, and writing the config file every time the resize event fires is way too performance taxing.
What would be the best/easiest way of monitoring for when the user is done resizing the frame?
My config_set
function:
def config_set(key, value):
"""Set a value to the config file."""
vprint(2, 'Setting config value: "{}": "{}"'.format(key, value))
config[key] = value
# Save the config file.
with open(config_file_path, 'w') as f:
pickle.dump(config, f)
Upvotes: 3
Views: 3126
Reputation: 6226
You could handle EVT_IDLE
which is triggered when the event queue is empty:
wx.IdleEvent: This class is used for EVT_IDLE events, which are generated and sent when the application becomes idle. In other words, the when the event queue becomes empty then idle events are sent to all windows (by default) and as long as none of them call RequestMore then there are no more idle events until after the system event queue has some normal events and then becomes empty again.
The process of resizing or moving a window should keep the event queue jammed so it won't become empty (and trigger the idle event) until the resizing/moving is done.
Set a dirty flag in EVT_SIZE
and check it in the EVT_IDLE
handler. If the flag is set, save the new size and reset the flag:
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
self.resized = False # the dirty flag
self.Bind(wx.EVT_SIZE,self.OnSize)
self.Bind(wx.EVT_IDLE,self.OnIdle)
def OnSize(self,event):
self.resized = True # set dirty
def OnIdle(self,event):
if self.resized:
# take action if the dirty flag is set
print "New size:", self.GetSize()
self.resized = False # reset the flag
app = wx.PySimpleApp()
frame = Frame().Show()
app.MainLoop()
EVT_SIZE
may also be triggered when restoring a minimized window (the window size remains the same). If you want to cut down on unnecessary saves, you may want to check if the size is actually different before you save it to the config (you could keep track of it in a variable containing the last saved size).
You may want to add EVT_MOVE
to keep track of the window position.
Upvotes: 6
Reputation: 22753
You definitely shouldn't be saving the window geometry on every resize, it should be normally only done when the frame is closed. If you want extra safety (but, honestly, how do you manage to crash in Python?), you can also call the same function you call on frame close from a EVT_TIMER
handler. But window geometry is hardly a critical resource so I don't think there is ever any real need to do this.
Upvotes: 1
Reputation: 33111
You could start a timer and have it check for changes every so often, kind of like the auto-save in Microsoft Word. Or you could set some kind of flag when EVT_SIZING or EVT_SIZE occurs and then bind to EVT_LEAVE_WINDOW as you'll almost certainly leave the window when you're done resizing. Thus when that event fires, you check the flag that was set and if it is set, you save and reset the flag.
Upvotes: 2
Reputation: 20616
On windows, you can save the configuration in the registry, which results in no performance hit when the window is resized.
On other OS's, where there is no registry, I guess you need to use a file. However, I am surprised that even this gives the kind of performance penalty that you would notice.
Are you sure that whatever poor performance you are seeing is due to this? ( Perhaps your redrawing code is slow? )
I would think that any modern OS would look after such a small file write without getting in your way. Perhaps it is Python problem?
I urge you to look into the above questions first. However, to answer your actual question:
The way to do this is to save the window size in a variable, and only write it to a file when your application quits.
Took a look at the code you just posted. I am not a python expert, but it looks like you are re-opening the file on every update. If so, no wonder it is slow!
Keep the file open all the time.
Only write the file when your app quits.
You might also take a look at the wxWidget wxConfig class.
Upvotes: 1