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/lib/matplotlib/__init__.py matplotlib-0.87.3.old/lib/matplotlib/__init__.py --- matplotlib-0.87.3/lib/matplotlib/__init__.py 2006-07-05 22:04:59.000000000 -0500 +++ matplotlib-0.87.3.old/lib/matplotlib/__init__.py 2006-07-05 22:02:14.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', - 'Qt4Agg', 'SVG', 'Template', 'TkAgg', 'WX', 'WXAgg', ] + 'GTKAgg', 'GTKCairo', 'FltkAgg', 'Paint', 'Pdf', 'PS', 'QtAgg', '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/lib/matplotlib/backends/__init__.py matplotlib-0.87.3.old/lib/matplotlib/backends/__init__.py --- matplotlib-0.87.3/lib/matplotlib/backends/__init__.py 2006-07-05 22:07:13.000000000 -0500 +++ matplotlib-0.87.3.old/lib/matplotlib/backends/__init__.py 2006-07-05 22:02:14.000000000 -0500 @@ -4,8 +4,8 @@ __all__ = ['backend','show','draw_if_interactive', 'new_figure_manager', 'backend_version'] -interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', 'Qt4Agg', - 'TkAgg', 'WX', 'WXAgg', 'CocoaAgg', 'Aqt'] +interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', '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/lib/matplotlib/backends/backend_qt4.py matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4.py --- matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4.py 2006-07-05 22:07:55.000000000 -0500 +++ matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4.py 1969-12-31 18:00:00.000000000 -0600 @@ -1,340 +0,0 @@ -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/lib/matplotlib/backends/backend_qt4agg.py matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4agg.py --- matplotlib-0.87.3/lib/matplotlib/backends/backend_qt4agg.py 2006-07-05 22:08:01.000000000 -0500 +++ matplotlib-0.87.3.old/lib/matplotlib/backends/backend_qt4agg.py 1969-12-31 18:00:00.000000000 -0600 @@ -1,127 +0,0 @@ -""" -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