Question

I'm creating a small tool for data visualization. The GUI is created with Pygtk and very simple. After the user has entered a filename he can press the button "calc" to see the output. The output is rendered by pycairo and presented in a gtk.DrawingArea.

The application works as following: When the button is pressed the file is processed and its content is stored in a special class. This class is a custom container: It's instantiated together with the gui and either empty or filled. The DrawingArea's expose event is linked to a drawing function that reads the container and draws its content. As long as the container is empty the DrawingArea remains empty but after calc has been clicked and a file was loaded the DrawingArea should be filled with my visuals.

The problem is: Everything works fine, except of updating the DrawingArea. I can't figure out how to manually invoke expose. After pressing calc I have to resize the window to see the result.

More specific: I've copied this code from a tutorial and don't know how to provide the parameter event myself:

def do_expose_event(self,event):
    # Create the cairo context
    cr = self.window.cairo_create()

    # Restrict Cairo to the exposed area; avoid extra work
    cr.rectangle(event.area.x, event.area.y,
            event.area.width, event.area.height)
    cr.clip()

    self.draw(cr, *self.window.get_size())
Was it helpful?

Solution

In order to have your widget refreshed, you need to tell GTK+ that it needs to be redrawn, typically using gtk.Widget.queue_draw() (called as self.queue_draw()), which invalidates your entire widget and schedules a redraw (by emitting expose events) that will take place after your program returns to the main loop.

If you need more control over the region being redrawn, you can always use gtk.Widget.queue_draw_area() to specify an area to invalidate, or go all the way down to gtk.gdk.Window.invalidate_rect().

OTHER TIPS

You've written a event callback, which you need to connect to the expose event like so:self.connect("do_expose_event", self.expose) in the __init__ method of your object.

Call self.draw() from the calc handler and forget about making a fake event structure to pass to expose.

But if you insist on misusing do_expose_event() by calling it directly, you don't need to create an entire event structure, just call it with the one element it references (event.area) set to the window geometry so that nothing gets clipped.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top