On Wed, Jan 14, 2009 at 10:19 AM,  <projet...@club-internet.fr> wrote:
> Hello,
>
> I'm searching for informations about using matplotlib interactively with 
> PyQt. I
> would like for example to move line with the mouse.

Start with the tutorial at

  http://matplotlib.sourceforge.net/users/event_handling.html

it has a draggable rectangle example.  matplotlib has its own even
model, so you do not need to use qt events explictly.  For example,
Paul Ivanov recently wrote pong using the matplotlib event system, and
then provided a gtk and qt version of them that requires no additional
gui programming save for starting up the window and event loop.  See
attached.  Paul's original message is below:

From: Paul Ivanov
To: me, Fernando
        
Hi John,

I got a little carried away in the berkeley py4science group a few weeks
back when we were looking into different possibilities for doing
animation in python.

Attached is a working implementation (scoreboard included) of pong
that's easily portable to different backends (I made a gtk and qt version).

Fernando thought you'd get a kick out of it, let me know if you think
it'd be worthwhile to include in matplotlib so I could clean it up some.

the instructions with all of the keys pop up at the beginning (but they
slow down the animation the most), you can press 't' to toggle showing
the instructions.

you can press 'g' to toggle showing the game in progress, 'a' to add a
puck into play, and 'n' to remove the distracting sinusoids.

best,
Paul Ivanov
#!/usr/bin/env python
# A matplotlib based game of Pong illustrating one way to write interactive
# animation which are easily ported to multiply backends
# pipong.py was written by Paul Ivanov <http://pirsquared.org>

import numpy as np
import matplotlib.pyplot as plt
from numpy.random import randn, randint

instructions = """
Player A:       Player B:
  'e'      up     'i'
  'd'     down    'k'

press 't' -- close these instructions 
            (animation will be much faster)
press 'a' -- add a puck                
press 'A' -- remove a puck             
press '1' -- slow down all pucks       
press '2' -- speed up all pucks        
press '3' -- slow down distractors     
press '4' -- speed up distractors      
press ' ' -- reset the first puck
press 'n' -- toggle distractors on/off    
press 'g' -- toggle the game on/off    

  """

class Pad(object):
    def __init__(self, disp,x,y,type='l'):
        self.disp = disp
        self.x = x
        self.y = y
        self.w = .3
        self.score = 0
        self.xoffset = 0.3
        self.yoffset = 0.1
        if type=='r':
            self.xoffset *= -1.0

        if type=='l' or type=='r':
            self.signx = -1.0
            self.signy = 1.0
        else:
            self.signx = 1.0
            self.signy = -1.0
    def contains(self, loc):
        return self.disp.get_bbox().contains(loc.x,loc.y)

class Puck(object):
    def __init__(self, disp, pad, field):
        self.vmax= .2
        self.disp = disp
        self.field = field
        self._reset(pad)
    def _reset(self,pad):
        self.x = pad.x + pad.xoffset
        if pad.y < 0:
            self.y = pad.y +  pad.yoffset 
        else:
            self.y = pad.y - pad.yoffset
        self.vx = pad.x - self.x
        self.vy = pad.y + pad.w/2 - self.y
        self._speedlimit()
        self._slower()
        self._slower()
    def update(self,pads):
        self.x += self.vx
        self.y += self.vy
        for pad in pads:
            if pad.contains(self):
                self.vx *= 1.2 *pad.signx
                self.vy *= 1.2 *pad.signy
        fudge = .001
        #probably cleaner with something like...if not self.field.contains(self.x, self.y):
        if self.x < 0+fudge:
            #print "player A loses"
            pads[1].score += 1;
            self._reset(pads[0])
            return True
        if self.x > 7-fudge:
            #print "player B loses"
            pads[0].score += 1;
            self._reset(pads[1])
            return True
        if self.y < -1+fudge or self.y > 1-fudge:
            self.vy *= -1.0 
            # add some randomness, just to make it interesting
            self.vy -= (randn()/300.0 + 1/300.0) * np.sign(self.vy)
        self._speedlimit()
        return False
    def _slower(self):
        self.vx /= 5.0
        self.vy /= 5.0
    def _faster(self):
        self.vx *= 5.0
        self.vy *= 5.0
    def _speedlimit(self):
        if self.vx > self.vmax:
            self.vx = self.vmax
        if self.vx < -self.vmax:
            self.vx = -self.vmax

        if self.vy > self.vmax:
            self.vy = self.vmax
        if self.vy < -self.vmax:
            self.vy = -self.vmax

class Game(object):        

    def __init__(self, ax):
        # create the initial line
        self.ax = ax
        padAx = padBx= .50
        padAy = padBy= .30
        padBx+=6.3
        pA, = self.ax.barh(padAy,.2, height=.3,color='k', alpha=.5, edgecolor='b',lw=2,label="Player B", animated=True)
        pB, = self.ax.barh(padBy,.2, height=.3, left=padBx, color='k',alpha=.5, edgecolor='r',lw=2,label="Player A",animated=True)

        # distractors
        self.x = np.arange(0,2.22*np.pi,0.01)
        self.line, = self.ax.plot(self.x, np.sin(self.x),"r", animated=True, lw=4)
        self.line2, = self.ax.plot(self.x, np.cos(self.x),"g", animated=True, lw=4)
        self.line3, = self.ax.plot(self.x, np.cos(self.x),"g", animated=True, lw=4)
        self.line4, = self.ax.plot(self.x, np.cos(self.x),"r", animated=True, lw=4)
        self.centerline,= self.ax.plot([3.5,3.5], [1,-1],'k',alpha=.5, animated=True,  lw=8)
        self.puckdisp = self.ax.scatter([1],[1],label='_nolegend_', s=200,c='g',alpha=.9,animated=True)

        self.canvas = self.ax.figure.canvas
        self.background = None
        self.cnt = 0
        self.distract = True
        self.res = 100.0
        self.on = False
        self.inst = True    # show instructions from the beginning
        self.background = None
        self.pads = []
        self.pads.append( Pad(pA,0,padAy))
        self.pads.append( Pad(pB,padBx,padBy,'r'))
        self.pucks =[] 
        self.i = self.ax.annotate(instructions,(.5,0.5),
                     name='monospace',
                     verticalalignment='center',
                     horizontalalignment='center',
                     multialignment='left',
                     textcoords='axes fraction',animated=True )
        self.canvas.mpl_connect('key_press_event', self.key_press)

    def draw(self, evt):
        draw_artist = self.ax.draw_artist
        if self.background is None:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        # restore the clean slate background
        self.canvas.restore_region(self.background)

        # show the distractors
        if self.distract:
            self.line.set_ydata(np.sin(self.x+self.cnt/self.res))
            self.line2.set_ydata(np.cos(self.x-self.cnt/self.res))
            self.line3.set_ydata(np.tan(self.x+self.cnt/self.res))
            self.line4.set_ydata(np.tan(self.x-self.cnt/self.res))
            draw_artist(self.line)
            draw_artist(self.line2)
            draw_artist(self.line3)
            draw_artist(self.line4)

        # show the instructions - this is very slow
        if self.inst:
            self.ax.draw_artist(self.i)

        # pucks and pads
        if self.on:
            self.ax.draw_artist(self.centerline)
            for pad in self.pads:
                pad.disp.set_y(pad.y)
                pad.disp.set_x(pad.x)
                self.ax.draw_artist(pad.disp)

            for puck in self.pucks:
                if puck.update(self.pads):
                    # we only get here if someone scored
                    self.pads[0].disp.set_label("   "+ str(self.pads[0].score)) 
                    self.pads[1].disp.set_label("   "+ str(self.pads[1].score)) 
                    self.ax.legend(loc='center')
                    self.leg = self.ax.get_legend()
                    #self.leg.draw_frame(False) #don't draw the legend border
                    self.leg.get_frame().set_alpha(.2)
                    plt.setp(self.leg.get_texts(),fontweight='bold',fontsize='xx-large')
                    self.leg.get_frame().set_facecolor('0.2')
                    self.background = None
                    self.ax.draw()
                    return True
                puck.disp.set_offsets([puck.x,puck.y])
                self.ax.draw_artist(puck.disp)


        # just redraw the axes rectangle
        self.canvas.blit(self.ax.bbox)

        if self.cnt==50000:
            # just so we don't get carried away
            print "...and you've been playing for too long!!!"
            plt.close()

        self.cnt += 1
        return True

    def key_press(self,event):
        if event.key == '3':
            self.res *= 5.0
        if event.key == '4':
            self.res /= 5.0

        if event.key == 'e':
            self.pads[0].y += .1
            if self.pads[0].y > 1 - .3:
                self.pads[0].y = 1-.3
        if event.key == 'd':
            self.pads[0].y -= .1
            if self.pads[0].y < -1:
                self.pads[0].y = -1

        if event.key == 'i':
            self.pads[1].y += .1
            if self.pads[1].y > 1 - .3:
                self.pads[1].y = 1-.3
        if event.key == 'k':
            self.pads[1].y -= .1
            if self.pads[1].y < -1:
                self.pads[1].y = -1
        
        if event.key == 'a':
            self.pucks.append(Puck(self.puckdisp,self.pads[randint(2)],self.ax.bbox))
        if event.key == 'A' and len(self.pucks):
            self.pucks.pop()
        if event.key == ' ' and len(self.pucks):
            self.pucks[0]._reset(self.pads[randint(2)])
        if event.key == '1':
            for p in self.pucks:
                p._slower()
        if event.key == '2':
            for p in self.pucks:
                p._faster()
        
        if event.key == 'n':
            self.distract = not self.distract

        if event.key == 'g':
            #self.ax.clear()
            #self.ax.grid() # seems to be necessary for qt backend
            self.on = not self.on
        if event.key == 't':
            self.inst = not self.inst
            self.i.set_visible(self.i.get_visible())
        if event.key == 'q':
            plt.close() 
#!/usr/bin/env python

# For detailed comments on animation and the techniques used here, see
# the wiki entry
# http://www.scipy.org/wikis/topical_software/MatplotlibAnimation
import time

import gtk, gobject

import matplotlib
matplotlib.use('GTKAgg')

import numpy as np
import matplotlib.pyplot as plt
import pipong 
from numpy.random import randn, randint


fig = plt.figure()
ax = fig.add_subplot(111)
canvas = ax.figure.canvas


def start_anim(event):
    gobject.idle_add(animation.draw,animation)
    canvas.mpl_disconnect(start_anim.cid)

animation = pipong.Game(ax)
start_anim.cid = canvas.mpl_connect('draw_event', start_anim)


tstart = time.time()
plt.grid() # to ensure proper background restore
plt.show()
print 'FPS:' , animation.cnt/(time.time()-tstart)
#!/usr/bin/env python

# For detailed comments on animation and the techniques used here, see
# the wiki entry
# http://www.scipy.org/wikis/topical_software/MatplotlibAnimation
import time

import gtk, gobject

import matplotlib
matplotlib.use('GTKAgg')

import numpy as np
import matplotlib.pyplot as plt
import pipong 
from numpy.random import randn, randint


fig = plt.figure()
ax = fig.add_subplot(111)
canvas = ax.figure.canvas


def start_anim(event):
    gobject.idle_add(animation.draw,animation)
    canvas.mpl_disconnect(start_anim.cid)

animation = pipong.Game(ax)
start_anim.cid = canvas.mpl_connect('draw_event', start_anim)


tstart = time.time()
plt.grid() # to ensure proper background restore
plt.show()
print 'FPS:' , animation.cnt/(time.time()-tstart)
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to