[pygtk] some more problems in moving a widget

Vihan Pandey vihanpandey at gmail.com
Thu Feb 16 19:11:17 WST 2006


Hello all,
             i'm still facing some problems in making a widget move.

For Johan :

i checked out :

http://cvs.gnome.org/viewcvs/gnome-python/pygtk/examples/gtk/widget.py?view=markup

and integrated the two programs (mine and the one above).


The resultant code :

import sys
import gobject
import pango
import gtk
from gtk import gdk


if gtk.pygtk_version < (2, 8):
    print "PyGtk 2.8 or later required for this example"
    raise SystemExit

try:
    import cairo
except ImportError:
    raise SystemExit("cairo required for this example")



class PyGtkWidget(gtk.Widget):
    def __init__(self):
        gtk.Widget.__init__(self)
        #self._layout = self.create_pango_layout(text)
        #self._layout.set_font_description(pango.FontDescription("Sans Serif
16"))

    # GtkWidget

    def do_realize(self):
        # The do_realize method is responsible for creating GDK (windowing
system)
        # resources. In this example we will create a new gdk.Window which
we
        # then draw on

        # First set an internal flag telling that we're realized
        self.set_flags(self.flags() | gtk.REALIZED)

        # Create a new gdk.Window which we can draw on.
        # Also say that we want to receive exposure events by setting
        # the event_mask
        self.window = gdk.Window(
            self.get_parent_window(),
            width=self.allocation.width,
            height=self.allocation.height,
            window_type=gdk.WINDOW_CHILD,
            wclass=gdk.INPUT_OUTPUT,
            event_mask=self.get_events() | gdk.EXPOSURE_MASK)

        # Associate the gdk.Window with ourselves, Gtk+ needs a reference
        # between the widget and the gdk window
    self.window.set_user_data(self)

        # Attach the style to the gdk.Window, a style contains colors and
        # GC contextes used for drawing
        self.style.attach(self.window)

        # The default color of the background should be what
        # the style (theme engine) tells us.
        self.style.set_background(self.window, gtk.STATE_NORMAL)
        self.window.move_resize(*self.allocation)

    def do_unrealize(self):
        # The do_unrealized method is responsible for freeing the GDK
resources

        # De-associate the window we created in do_realize with ourselves
    self.window.set_user_data(None)

    def do_size_request(self, requisition):
        # The do_size_request method Gtk+ is calling on a widget to ask
        # it the widget how large it wishes to be. It's not guaranteed
        # that gtk+ will actually give this size to the widget

        # In this case, we say that we want to be as big as the
        # text is, plus a little border around it.
    width, height = self._layout.get_size()
    requisition.width = width // pango.SCALE + BORDER_WIDTH*4
    requisition.height = height // pango.SCALE + BORDER_WIDTH*4

    def do_size_allocate(self, allocation):
        # The do_size_allocate is called by when the actual size is known
        # and the widget is told how much space could actually be allocated

        # Save the allocated space
        self.allocation = allocation

        # If we're realized, move and resize the window to the
        # requested coordinates/positions
        if self.flags() & gtk.REALIZED:
            self.window.move_resize(*allocation)

    def do_expose_event(self, widget, event):
        # The do_expose_event is called when the widget is asked to draw
itself
        # Remember that this will be called a lot of times, so it's usually
        # a good idea to write this code as optimized as it can be, don't
        # Create any resources in here.

        # In this example, draw a rectangle in the foreground color

        self.context = widget.window.cairo_create()

        # set a clip region for the expose event

        self.context.rectangle(event.area.x,
                           event.area.y,
                   event.area.width,
                   event.area.height)
        self.context.clip()

        #self.draw(self.context)

        return False

    #def draw(self, context):
        rect = self.get_allocation()

    x = rect.width / 2
    print 'X cordinate is : '
    print x
        y = rect.height / 2
    print 'Y cordinate is : '
    print y

    # Ellipse co-ordinates, default : centroid of Rectangle
    ex = x
    ey = y

    ew = rect.width / 4.0
    eh = rect.height / 12.0

    context.save()

    context.translate (ex, ey)

    # edited by vihan
    context.scale (ew / 2.0 , eh / 2.0)

    #context.arc (0, 0, 1., 0., 2 * math.pi)


    # edited by vihan
    #
    # context.arc(x displacement, y displacement, 'another ellipse',
    #        'slice ellipse', start point, end point
    #
    context.arc (0, 0, 1., 0, 2 * math.pi)

    context.fill_preserve()

        # This sets the colour of the Ellipse via R, G, B levels 0.0 - 1.0
        context.set_source_rgb(0, 0, 1)


        context.stroke()
    context.restore ()

gobject.type_register(PyGtkWidget)

def main(args):
    win = gtk.Window()
    win.set_border_width(5)
    win.set_title('Widget test')
    win.connect('delete-event', gtk.main_quit)

    frame = gtk.Frame("Example frame")
    win.add(frame)

    w = PyGtkWidget(TEXT)
    frame.add(w)

    win.show_all()

    gtk.main()


def main(args):
    win = gtk.Window()
    win.set_border_width(5)
    win.set_title('Widget test')
    win.connect('delete-event', gtk.main_quit)

    frame = gtk.Frame("Example frame")
    win.add(frame)

    w = PyGtkWidget()
    frame.add(w)

    win.show_all()

    gtk.main()

if __name__ == '__main__':
    sys.exit(main(sys.argv))





But i get the follwing error :


Traceback (most recent call last):
  File "ellipse-move.py", line 73, in do_size_request
    width, height = self._layout.get_size()
AttributeError: 'PyGtkWidget' object has no attribute '_layout'
TypeError: do_expose_event() takes exactly 3 arguments (2 given)


i never faced this in the ellipse prototypes. There's another question
around the same, why is it that one can only add one widget object onto a
gtk drawing area ? i tried the following :

import gtk
import math

class Ellipse(gtk.DrawingArea):
    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.connect("expose_event", self.expose)

    def expose(self, widget, event):
        self.context = widget.window.cairo_create()

        # set a clip region for the expose event
        self.context.rectangle(event.area.x, event.area.y,
                               event.area.width, event.area.height)
        self.context.clip()

        self.draw(self.context)

        return False

    def draw(self, context):
        rect = self.get_allocation()

    x = rect.width / 2
    print 'X cordinate is : '
    print x
        y = rect.height / 2
    print 'Y cordinate is : '
    print y

    # Ellipse co-ordinates, default : centroid of Rectangle
    ex = x
    ey = y



    ew = rect.width / 4.0
    eh = rect.height / 12.0

    context.save()

    context.translate (ex, ey)

    # edited by vihan
    context.scale (ew / 2.0 , eh / 2.0)

    #context.arc (0, 0, 1., 0., 2 * math.pi)


    # edited by vihan
    #
    # context.arc(x displacement, y displacement, 'another ellipse',
    #        'slice ellipse', start point, end point
    #
    context.arc (0, 0, 1., 0, 2 * math.pi)


    context.fill_preserve()


        # This sets the colour of the Ellipse via R, G, B levels 0.0 - 1.0
        context.set_source_rgb(0, 0, 1)


        context.stroke()
    context.restore ()

#### End of class Ellipse ####




class myclass(gtk.DrawingArea):
    #def __init__(self):
    #    gtk.DrawingArea.__init__(self)
    #    self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
    #            gtk.gdk.BUTTON1_MOTION_MASK)

    #    self.connect("expose_event", self.expose)
    #    self.connect("button_press_event", self.pressing)
    #    self.connect("motion_notify_event", self.moving)


    #    self.desp = 0

    def pressing(self, widget, event):
        self.pressing_x = event.x

    def moving(self, widget, event):
        if (self.pressing_x - event.x) > 1:
            self.desp = self.desp + 0.1
        else:
            self.desp = self.desp - 0.1

        self.pressing_x = event.x


        self.draw(self.context)

        self.queue_draw()

    def expose(self, widget, event):
        self.context = widget.window.cairo_create()

        self.context.rectangle(event.area.x, event.area.y,
                event.area.width, event.area.height)
        self.context.clip()

        self.draw(self.context)
        return False

    def draw(self, context):

            x = 100 / 2
             y = 50 / 2

        context.rectangle (x + self.desp, y + self.desp, 100, 50)
            context.set_source_rgb(1, 1, 1)
            context.fill_preserve()
            context.set_source_rgb(0, 0, 0)
            context.stroke()


def main():
    window = gtk.Window()
    eobj = Ellipse()
    eobj2 = Ellipse
    robj = myclass()

    window.add(eobj)
    window.add(robj)
    #window.add(eobj2)
    window.connect("destroy", gtk.main_quit)
    window.show_all()

    gtk.main()

if __name__ == "__main__":
    main()



This creates a 2 ellipse objects and adds them to the window. However you
can only display one at a time.



On uncommenting the     window.add(eobj2)  line you get the error ;

multiwidget.py:133: GtkWarning: Attempting to add a widget with type
GtkDrawingArea to a GtkWindow, but as a GtkBin subclass a GtkWindow can only
contain one widget at a time; it already contains a widget of type
GtkDrawingArea
  window.add(robj)
Traceback (most recent call last):
  File "multiwidget.py", line 141, in ?
    main()
  File "multiwidget.py", line 134, in main
    window.add(eobj2)
TypeError: GtkContainer.add() argument 1 must be gtk.Widget, not
gobject.GObjectMeta


Does anyone why is this so. Moreover how do i add more than one widget onto
the window.

Sorry for me repeatedly bothering every one with my "Ellipse obsession" but
i just can't seem to get it right.

Thanks,

- vihan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.daa.com.au/pipermail/pygtk/attachments/20060216/bc333ef6/attachment-0001.htm


More information about the pygtk mailing list