Hubro
Hubro

Reputation: 59408

What is the simplest way of monitoring when a wxPython frame has been resized?

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?


Update

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

Answers (4)

Anonymous Coward
Anonymous Coward

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

VZ.
VZ.

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

Mike Driscoll
Mike Driscoll

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

ravenspoint
ravenspoint

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!

  1. Keep the file open all the time.

  2. Only write the file when your app quits.

You might also take a look at the wxWidget wxConfig class.

Upvotes: 1

Related Questions