Oops.  The earlier patch was reversed by accident.  Here is the fixed patch.

On Wednesday 05 July 2006 22:30, you wrote:
> Hi all
>    I ported the QtAgg backend over to Qt4 and created a patch for adding
> this backend to matplotlib with the name, Qt4Agg.  I include it here, for
> anyone interested.   I also noticed an earlier message like this, seemingly
> without resolution.   Is there other- maybe, better- code for Qt4 available
> somewhere?
>
> Kevin Mueller
> Dept. Atmospheric Science, Univ. Illinois Urbana-Qt4Champaign
diff -Naur matplotlib-0.87.3.old/lib/matplotlib/__init__.py matplotlib-0.87.3/lib/matplotlib/__init__.py
--- matplotlib-0.87.3.old/lib/matplotlib/__init__.py	2006-07-05 22:02:14.000000000 -0500
+++ matplotlib-0.87.3/lib/matplotlib/__init__.py	2006-07-05 22:04:59.000000000 -0500
@@ -467,8 +467,8 @@
 def validate_backend(s, fail_on_err = True):
     s=s.lower()
     backends = ['Agg2', 'Agg', 'Aqt', 'Cairo', 'CocoaAgg', 'EMF', 'GD', 'GDK', 'GTK',
-                'GTKAgg', 'GTKCairo', 'FltkAgg', 'Paint', 'Pdf', 'PS', 'QtAgg', 'SVG',
-                'Template', 'TkAgg', 'WX', 'WXAgg', ]
+                'GTKAgg', 'GTKCairo', 'FltkAgg', 'Paint', 'Pdf', 'PS', 'QtAgg', 
+                'Qt4Agg', 'SVG', 'Template', 'TkAgg', 'WX', 'WXAgg', ]
     for i in backends:
         if s == i.lower(): return i
     if fail_on_err: raise ValueError('Backend must be %s, or %s'% \
diff -Naur matplotlib-0.87.3.old/lib/matplotlib/backends/__init__.py matplotlib-0.87.3/lib/matplotlib/backends/__init__.py
--- matplotlib-0.87.3.old/lib/matplotlib/backends/__init__.py	2006-07-05 22:02:14.000000000 -0500
+++ matplotlib-0.87.3/lib/matplotlib/backends/__init__.py	2006-07-05 22:07:13.000000000 -0500
@@ -4,8 +4,8 @@
 __all__ = ['backend','show','draw_if_interactive',
            'new_figure_manager', 'backend_version']
 
-interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', 'TkAgg', 
-                  'WX', 'WXAgg', 'CocoaAgg', 'Aqt']
+interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', 'Qt4Agg',
+                  'TkAgg', 'WX', 'WXAgg', 'CocoaAgg', 'Aqt']
 non_interactive_bk = ['Agg2', 'Agg', 'Cairo', 'EMF', 'GD', 'GDK', 'Paint', 
 		      'Pdf', 'PS', 'SVG', 'Template']
 all_backends = interactive_bk + non_interactive_bk
diff -Naur matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4.py matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4.py
--- matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4.py	1969-12-31 18:00:00.000000000 -0600
+++ matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4.py	2006-07-05 22:07:55.000000000 -0500
@@ -0,0 +1,340 @@
+from __future__ import division
+import math
+import os
+import sys
+
+import matplotlib
+from matplotlib import verbose
+from matplotlib.numerix import asarray, fromstring, UInt8, zeros, \
+     where, transpose, nonzero, indices, ones, nx
+import matplotlib.numerix as numerix
+from matplotlib.cbook import is_string_like, enumerate, onetrue
+from matplotlib.font_manager import fontManager
+from matplotlib.backend_bases import RendererBase, GraphicsContextBase, \
+     FigureManagerBase, FigureCanvasBase, NavigationToolbar2, cursors
+from matplotlib._pylab_helpers import Gcf
+from matplotlib.figure import Figure
+from matplotlib.mathtext import math_parse_s_ft2font
+
+from PyQt4 import QtCore, QtGui
+
+backend_version = "0.9.1"
+def fn_name(): return sys._getframe(1).f_code.co_name
+
+DEBUG = False
+
+cursord = {
+    cursors.MOVE          : QtCore.Qt.PointingHandCursor,
+    cursors.HAND          : QtCore.Qt.WaitCursor,
+    cursors.POINTER       : QtCore.Qt.ArrowCursor,
+    cursors.SELECT_REGION : QtCore.Qt.CrossCursor,
+    }
+
+def draw_if_interactive():
+    """
+    Is called after every pylab drawing command
+    """
+    if matplotlib.is_interactive():
+        figManager =  Gcf.get_active()
+        if figManager != None:
+            figManager.canvas.draw()
+
+def show( mainloop=True ):
+    """
+    Show all the figures and enter the qt main loop
+    This should be the last line of your script
+    """
+    for manager in Gcf.get_all_fig_managers():
+        manager.window.show()
+        
+    if DEBUG: print 'Inside show'
+    figManager =  Gcf.get_active()
+    if figManager != None:
+        figManager.canvas.draw()
+        #if ( createQApp ):
+        #   qtapplication.setMainWidget( figManager.canvas )
+
+    if mainloop and createQApp:
+        QtCore.QObject.connect( qtapplication, QtCore.SIGNAL( "lastWindowClosed()" ),
+                            qtapplication, QtCore.SLOT( "quit()" ) )
+        qtapplication.exec_()    
+
+
+def new_figure_manager( num, *args, **kwargs ):
+    """
+    Create a new figure manager instance
+    """
+    thisFig = Figure( *args, **kwargs )
+    canvas = FigureCanvasQT( thisFig )
+    manager = FigureManagerQT( canvas, num )
+    return manager
+
+
+class FigureCanvasQT( QtGui.QWidget, FigureCanvasBase ):
+    keyvald = { QtCore.Qt.Key_Control : 'control',
+                QtCore.Qt.Key_Shift : 'shift',
+                QtCore.Qt.Key_Alt : 'alt',
+               }
+    # left 1, middle 2, right 3
+    buttond = {1:1, 2:3, 4:2}
+    def __init__( self, figure ):
+        if DEBUG: print 'FigureCanvasQt: ', figure
+        FigureCanvasBase.__init__( self, figure )
+        QtGui.QWidget.__init__( self, None )
+        self.figure = figure
+        self.setMouseTracking( True )
+
+        w,h = self.get_width_height()
+        self.resize( w, h )
+        
+    def mousePressEvent( self, event ):
+        x = event.pos().x()
+        # flipy so y=0 is bottom of canvas
+        y = self.figure.bbox.height() - event.pos().y()
+        button = self.buttond[event.button()]
+        FigureCanvasBase.button_press_event( self, x, y, button )
+        if DEBUG: print 'button pressed:', event.button()
+        
+    def mouseMoveEvent( self, event ):
+        x = event.x()
+        # flipy so y=0 is bottom of canvas
+        y = self.figure.bbox.height() - event.y()
+        FigureCanvasBase.motion_notify_event( self, x, y )
+        if DEBUG: print 'mouse move'
+
+    def mouseReleaseEvent( self, event ):
+        x = event.x()
+        # flipy so y=0 is bottom of canvas
+        y = self.figure.bbox.height() - event.y()
+        button = self.buttond[event.button()]
+        FigureCanvasBase.button_release_event( self, x, y, button )
+        if DEBUG: print 'button released'
+        self.draw()
+
+    def keyPressEvent( self, event ):
+        key = self._get_key( event )
+        FigureCanvasBase.key_press_event( self, key )
+        if DEBUG: print 'key press', key
+
+    def keyReleaseEvent( self, event ):
+        key = self._get_key(event)
+        FigureCanvasBase.key_release_event( self, key )
+        if DEBUG: print 'key release', key
+
+    def resizeEvent( self, event ):
+        if DEBUG: print 'resize (%d x %d)' % (event.size().width(), event.size().height())
+        QtGui.QWidget.resizeEvent( self, event )
+
+    def resize( self, w, h ):
+        QtGui.QWidget.resize( self, w, h )
+
+    def _get_key( self, event ):
+        if event.key() < 256:
+            key = event.text().latin1()
+        elif self.keyvald.has_key( event.key() ):
+            key = self.keyvald[ event.key() ]
+        else:
+            key = None
+            
+        return key
+
+class FigureManagerQT( FigureManagerBase ):
+    """
+    Public attributes
+
+    canvas      : The FigureCanvas instance
+    num         : The Figure number
+    toolbar     : The QtGui.QToolBar
+    window      : The QtGui.QMainWindow 
+    """
+    
+    def __init__( self, canvas, num ):
+        if DEBUG: print 'FigureManagerQT.%s' % fn_name()
+        FigureManagerBase.__init__( self, canvas, num )
+        self.canvas = canvas
+        self.window = QtGui.QMainWindow()
+        self.window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
+
+        centralWidget = QtGui.QWidget( self.window )
+        self.canvas.setParent( centralWidget )
+        
+        # Give the keyboard focus to the figure instead of the manager
+        self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
+        self.canvas.setFocus()
+        self.window.setWindowTitle( "Figure %d" % num )
+
+        QtCore.QObject.connect( self.window, QtCore.SIGNAL( 'destroyed()' ),
+                            self._widgetclosed )
+        self.window._destroying = False
+
+        if matplotlib.rcParams['toolbar'] == 'classic':
+            print "Classic toolbar is not yet supported"
+            #self.toolbar = NavigationToolbarQT( centralWidget, canvas )
+            self.toolbar = None
+        elif matplotlib.rcParams['toolbar'] == 'toolbar2':
+            self.toolbar = NavigationToolbar2QT( centralWidget, canvas )
+        else:
+            self.toolbar = None
+
+        # Use a vertical layout for the plot and the toolbar.  Set the
+        # stretch to all be in the plot so the toolbar doesn't resize.
+        layout = QtGui.QVBoxLayout( centralWidget )
+        layout.addWidget( self.canvas, 1 )
+        if self.toolbar:
+           layout.addWidget( self.toolbar, 0 )
+
+        self.window.setCentralWidget( centralWidget )
+
+        # Reset the window height so the canvas will be the right
+        # size.  This ALMOST works right.  The first issue is that the
+        # height w/ a toolbar seems to be off by just a little bit (so
+        # we add 4 pixels).  The second is that the total width/height
+        # is slightly smaller that we actually want.  It seems like
+        # the border of the window is being included in the size but
+        # AFAIK there is no way to get that size.  
+        w = self.canvas.width()
+        h = self.canvas.height()
+        if self.toolbar:
+           h += self.toolbar.height() + 4
+        self.window.resize( w, h )
+        
+        if matplotlib.is_interactive():
+            self.window.show()
+
+        def notify_axes_change( fig ):
+           # This will be called whenever the current axes is changed
+           if self.toolbar != None: self.toolbar.update()
+           self.canvas.figure.add_axobserver( notify_axes_change )
+
+    def _widgetclosed( self ):
+        if self.window._destroying: return
+        self.window._destroying = True
+        Gcf.destroy(self.num)
+
+    def destroy( self, *args ):
+        if self.window._destroying: return
+        self.window._destroying = True
+        if DEBUG: print "destroy figure manager"
+        self.window.close(True)
+
+class NavigationToolbar2QT( NavigationToolbar2, QtGui.QWidget ):
+    # list of toolitems to add to the toolbar, format is:
+    # text, tooltip_text, image_file, callback(str)
+    toolitems = (
+        ('Home', 'Reset original view', 'home.ppm', 'home'),
+        ('Back', 'Back to  previous view','back.ppm', 'back'),
+        ('Forward', 'Forward to next view','forward.ppm', 'forward'),
+        (None, None, None, None),        
+        ('Pan', 'Pan axes with left mouse, zoom with right', 'move.ppm', 'pan'),
+        ('Zoom', 'Zoom to rectangle','zoom_to_rect.ppm', 'zoom'),
+        (None, None, None, None),
+        ('Save', 'Save the figure','filesave.ppm', 'save_figure'),
+        )
+        
+    def __init__( self, parent, canvas ):
+        self.canvas = canvas
+        QtGui.QWidget.__init__( self, parent )
+
+        # Layout toolbar buttons horizontally.
+        self.layout = QtGui.QHBoxLayout( self )
+        self.layout.setMargin( 2 )
+        
+        NavigationToolbar2.__init__( self, canvas )
+        
+    def _init_toolbar( self ):
+        basedir = matplotlib.rcParams[ 'datapath' ]
+        
+        for text, tooltip_text, image_file, callback in self.toolitems:
+            if text == None:
+                self.layout.addSpacing( 8 )
+                continue
+            
+            fname = os.path.join( basedir, image_file )
+            image = QtGui.QPixmap()
+            image.load( fname )
+
+            button = QtGui.QToolButton()
+            button.setIcon(QtGui.QIcon( image ))
+            button.setToolTip( tooltip_text )
+
+            # The automatic layout doesn't look that good - it's too close
+            # to the images so add a margin around it.
+            margin = 4
+            button.setFixedSize( image.width()+margin, image.height()+margin )
+
+            QtCore.QObject.connect( button, QtCore.SIGNAL( 'clicked()' ),
+                                getattr( self, callback ) )
+            self.layout.addWidget( button )
+
+        # Add the x,y location widget at the right side of the toolbar
+        # The stretch factor is 1 which means any resizing of the toolbar
+        # will resize this label instead of the buttons.
+        self.locLabel = QtGui.QLabel( "", self )
+        self.locLabel.setAlignment( QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter )
+        self.layout.addWidget( self.locLabel, 1 )
+
+    def dynamic_update( self ):
+        self.canvas.draw()
+
+    def set_message( self, s ):
+        self.locLabel.setText( s )
+
+    def set_cursor( self, cursor ):
+        if DEBUG: print 'Set cursor' , cursor
+        QtGui.QApplication.restoreOverrideCursor()
+        QtGui.QApplication.setOverrideCursor( QtGui.QCursor( cursord[cursor] ) )
+                
+    def draw_rubberband( self, event, x0, y0, x1, y1 ):
+        height = self.canvas.figure.bbox.height()
+        y1 = height - y1
+        y0 = height - y0
+        
+        w = abs(x1 - x0)
+        h = abs(y1 - y0)
+
+        rect = [ int(val)for val in min(x0,x1), min(y0, y1), w, h ]
+        self.canvas.drawRectangle( rect )
+    
+    def save_figure( self ):     
+        fname = QtGui.QFileDialog.getSaveFileName()
+        if fname:
+            self.canvas.print_figure( str(fname) )
+
+# set icon used when windows are minimized
+try:
+    QtGui.window_set_default_icon_from_file (
+        os.path.join( matplotlib.rcParams['datapath'], 'matplotlib.svg' ) )
+except:
+    verbose.report( 'Could not load matplotlib icon: %s' % sys.exc_info()[1] )
+
+
+def error_msg_qt( msg, parent=None ):
+    if not is_string_like( msg ):
+        msg = ','.join( map( str,msg ) )
+                         
+    QtGui.QMessageBox.warning( None, "Matplotlib", msg, QtGui.QMessageBox.Ok )
+
+def exception_handler( type, value, tb ):
+    """Handle uncaught exceptions
+    It does not catch SystemExit
+    """
+    msg = ''
+    # get the filename attribute if available (for IOError)
+    if hasattr(value, 'filename') and value.filename != None:
+        msg = value.filename + ': '
+    if hasattr(value, 'strerror') and value.strerror != None:
+        msg += value.strerror
+    else:
+        msg += str(value)
+
+    if len( msg ) : error_msg_qt( msg )
+
+
+FigureManager = FigureManagerQT
+
+# We need one and only one QApplication before we can build any Qt widgets
+# Detect if a QApplication exists.
+createQApp = QtGui.QApplication.startingUp()
+if createQApp:
+    if DEBUG: print "Starting up QApplication"
+    qtapplication = QtGui.QApplication( [" "] )
diff -Naur matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4agg.py matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4agg.py
--- matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4agg.py	1969-12-31 18:00:00.000000000 -0600
+++ matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4agg.py	2006-07-05 22:08:01.000000000 -0500
@@ -0,0 +1,127 @@
+"""
+Render to qt4 from agg
+"""
+from __future__ import division
+
+import os, sys
+from matplotlib import verbose
+from matplotlib.cbook import enumerate
+from matplotlib.figure import Figure
+
+from backend_agg import FigureCanvasAgg
+from backend_qt4 import FigureManagerQT, FigureCanvasQT,\
+     show, draw_if_interactive, backend_version
+import struct
+
+from PyQt4 import QtCore, QtGui
+
+DEBUG = False
+isLittleEndian = struct.pack('@i',7)=='\x07\x00\x00\x00'
+
+def new_figure_manager( num, *args, **kwargs ):
+    """
+    Create a new figure manager instance
+    """
+    if DEBUG: print 'backend_qt4agg.new_figure_manager'
+    thisFig = Figure( *args, **kwargs )
+    canvas = FigureCanvasQTAgg( thisFig )
+    return FigureManagerQT( canvas, num )
+
+class FigureCanvasQTAgg( FigureCanvasQT, FigureCanvasAgg ):
+    """
+    The canvas the figure renders into.  Calls the draw and print fig
+    methods, creates the renderers, etc...
+
+    Public attribute
+
+      figure - A Figure instance
+   """
+
+    def __init__( self, figure ):
+        if DEBUG: print 'FigureCanvasQtAgg: ', figure
+        FigureCanvasQT.__init__( self, figure )
+        FigureCanvasAgg.__init__( self, figure )
+        self.drawRect = False
+        self.rect = []
+        self.replot = True
+        self.pixmap = QtGui.QPixmap()
+     
+    def resizeEvent( self, e ):
+        FigureCanvasQT.resizeEvent( self, e )
+        w = e.size().width()
+        h = e.size().height()
+        if DEBUG: print "FigureCanvasQtAgg.resizeEvent(", w, ",", h, ")"
+        dpival = self.figure.dpi.get()
+        winch = w/dpival
+        hinch = h/dpival
+        self.figure.set_figsize_inches( winch, hinch )
+        self.draw()
+        
+    def drawRectangle( self, rect ):
+        self.rect = rect
+        self.drawRect = True
+        # False in repaint does not clear the image before repainting
+        self.repaint()
+
+    def paintEvent( self, e ):
+        """
+        Draw to the Agg backend and then copy the image to the QtGui.drawable.
+        In Qt, all drawing should be done inside of here when a widget is
+        shown onscreen.
+        """
+        
+        FigureCanvasQT.paintEvent( self, e )
+        if DEBUG: print 'FigureCanvasQtAgg.paintEvent: ', \
+           self.get_width_height()
+
+        p = QtGui.QPainter( self )
+        FigureCanvasAgg.draw( self )
+
+        # only replot data when needed
+        if ( self.replot ):
+            stringBuffer = str( self.buffer_rgba(0,0) )
+            
+
+            # matplotlib is in rgba byte order.
+            # qImage wants to put the bytes into argb format and
+            # is in a 4 byte unsigned int.  little endian system is LSB first
+            # and expects the bytes in reverse order (bgra).
+            # TODO: fix this to choose correct endian
+            if isLittleEndian:
+                stringBuffer = self.renderer._renderer.tostring_bgra()
+            else:
+                stringBuffer = self.renderer._renderer.tostring_argb()
+               
+            qImage = QtGui.QImage( stringBuffer, self.renderer.width,
+                                self.renderer.height, QtGui.QImage.Format_ARGB32)
+                
+            self.pixmap = QtGui.QPixmap.fromImage( qImage )
+    
+        p.drawPixmap( 0, 0, self.pixmap )
+
+        # draw the zoom rectangle to the QPainter
+        if ( self.drawRect ):
+            p.setPen( QtGui.QPen( QtCore.Qt.black, 1, QtCore.Qt.DotLine ) )
+            p.drawRect( self.rect[0], self.rect[1], self.rect[2], self.rect[3] )
+           
+        p.end()
+        self.replot = False
+        self.drawRect = False
+
+    def draw( self ):
+        """
+        Draw the figure when xwindows is ready for the update
+        """
+        
+        if DEBUG: print "FigureCanvasQtAgg.draw"
+        self.replot = True
+        self.repaint()
+        self.update()
+
+    def print_figure( self, filename, dpi=150, facecolor='w', edgecolor='w',
+                      orientation='portrait' ):
+        if DEBUG: print 'FigureCanvasQTAgg.print_figure'
+        agg = self.switch_backends( FigureCanvasAgg )
+        agg.print_figure( filename, dpi, facecolor, edgecolor, orientation )
+
+        
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to