8000 Backend plt/gcf refactor by tacaswell · Pull Request #2624 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Backend plt/gcf refactor #2624

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5501f4e
first steps to extract FigureManager* and friends from pyplot
tacaswell Nov 29, 2013
373909d
split backend_qt4 into two parts, with and without Gcf
tacaswell Nov 29, 2013
3014931
split backend_qt4agg into two parts.
tacaswell Nov 29, 2013
37e600e
Added a demo-file to show how to use the FigureManager classes to
tacaswell Nov 29, 2013
82f3dea
removed un-needed import of Gcf
tacaswell Nov 29, 2013
1ad0ebf
pep8 on backend_gtk.py
tacaswell Dec 3, 2013
58ea364
pep8 clean up in backend_gdk
tacaswell Dec 3, 2013
f355c0c
removed un-needed Gcf import
tacaswell Dec 3, 2013
d5e47fb
split backend_gcf into two parts,
tacaswell Dec 3, 2013
87781c5
pep8 on backend_gtkagg.py
tacaswell Dec 3, 2013
8000 ce7c2ac
split backend_gktagg.py in to two parts
tacaswell Dec 3, 2013
ec24d0c
updated exclude list
tacaswell Dec 3, 2013
d3ecb67
pep8 clean up on backend_gtk3.py
tacaswell Dec 3, 2013
26fc122
split backend_gtk3 into two parts
tacaswell Dec 3, 2013
fe7cdc0
updated coding standards
tacaswell Dec 3, 2013
b099ddd
pep8 on backend_gtkcairo.py
tacaswell Dec 4, 2013
70939fe
split backend_gtkcairo.py into Gcf dependent and independent
tacaswell Dec 4, 2013
4ec7908
import from _backend_bases in backend_agg to avoid implicit Gcf import
tacaswell Dec 4, 2013
4f9f5b5
pep8 on backend_agg.py
tacaswell Dec 4, 2013
03e86ee
split backend_gtk3agg.py into two parts, the gcf dependent and
tacaswell Dec 4, 2013
d97d98f
updated coding standards exclude list
tacaswell Dec 4, 2013
83caa44
pep8 on backend_gtk3cairo.py
tacaswell Dec 4, 2013
9e74042
pep8 on backend_cairo.py
tacaswell Dec 4, 2013
51ccd5e
changed backend_cairo.py to import from _backend_bases to avoid
tacaswell Dec 4, 2013
efb1881
updated coding standards
tacaswell Dec 4, 2013
f4bdd22
Split backend_gtk3cairo.py into two parts, one dependent on Gcf
tacaswell Dec 4, 2013
a4bda49
Updated embedding_with_qt4_manager.py
tacaswell Dec 5, 2013
407b1ee
Improved class-aliases in _backend_qt*.py
tacaswell Dec 5, 2013
03c43aa
adjusting imports
fariza Dec 18, 2013
35afa92
renamed _backend_bases.py -> base_backend_bases.py
tacaswell Jan 30, 2014
2b213c0
massive rename operation
tacaswell Jan 30, 2014
93fc457
removed rouge merge notation
tacaswell Jan 30, 2014
6401be2
fixed broken import
tacaswell Jan 30, 2014
3ea9f08
pep8 on backend_tkagg.py
tacaswell Jan 30, 2014
b528125
pep8 conformance
tacaswell Jan 31, 2014
1dde78d
removed files that no longer exist
tacaswell Jan 31, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
split backend_qt4agg into two parts.
One part (_backend_qt4Agg.py) has no dependencies on Gcf or pyplot,
which are all collected in backend_qt4agg.py.

Should be fully back-wards compatible.
  • Loading branch information
tacaswell committed Jan 30, 2014
commit 3014931eaf65dfd24543fa5d91bc1e1d8a2d8c9f
164 changes: 164 additions & 0 deletions lib/matplotlib/backends/_backend_qt4agg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
"""
Render to qt from agg
"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)

import six

import sys
import ctypes

import matplotlib
from matplotlib.figure import Figure
# grab Agg canvas
from .backend_agg import FigureCanvasAgg
# grab the qt4 compat stuff directly
from .qt4_compat import QtCore, QtGui

# grab the Gcf-less qt4 classes
from ._backend_qt4 import FigureManagerQT
from ._backend_qt4 import FigureCanvasQT
from ._backend_qt4 import NavigationToolbar2QT

DEBUG = False

_decref = ctypes.pythonapi.Py_DecRef
_decref.argtypes = [ctypes.py_object]
_decref.restype = None


def new_figure_manager(num, *args, **kwargs):
"""
Create a new figure manager instance
"""
if DEBUG:
print('backend_qtagg.new_figure_manager')
FigureClass = kwargs.pop('FigureClass', Figure)
thisFig = FigureClass(*args, **kwargs)
return new_figure_manager_given_figure(num, thisFig)


def new_figure_manager_given_figure(num, figure):
"""
Create a new figure manager instance for the given figure.
"""
canvas = FigureCanvasQTAgg(figure)
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.blitbox = None
self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)

def drawRectangle(self, rect):
self.rect = rect
self.drawRect = True
self.repaint()

def paintEvent(self, e):
"""
Copy the image from the Agg canvas to the qt.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,
self.get_width_height())

if self.blitbox is None:
# 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).
if QtCore.QSysInfo.ByteOrder == QtCore.QSysInfo.LittleEndian:
stringBuffer = self.renderer._renderer.tostring_bgra()
else:
stringBuffer = self.renderer._renderer.tostring_argb()

refcnt = sys.getrefcount(stringBuffer)

# convert the Agg rendered image -> qImage
qImage = QtGui.QImage(stringBuffer, self.renderer.width,
self.renderer.height,
QtGui.QImage.Format_ARGB32)
# get the rectangle for the image
rect = qImage.rect()
p = QtGui.QPainter(self)
# reset the image area of the canvas to be the back-ground color
p.eraseRect(rect)
# draw the rendered image on to the canvas
p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage))

# 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()

# This works around a bug in PySide 1.1.2 on Python 3.x,
# where the reference count of stringBuffer is incremented
# but never decremented by QImage.
# TODO: revert PR #1323 once the issue is fixed in PySide.
del qImage
if refcnt != sys.getrefcount(stringBuffer):
_decref(stringBuffer)
else:
bbox = self.blitbox
l, b, r, t = bbox.extents
w = int(r) - int(l)
h = int(t) - int(b)
t = int(b) + h
reg = self.copy_from_bbox(bbox)
stringBuffer = reg.to_string_argb()
qImage = QtGui.QImage(stringBuffer, w, h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
p = QtGui.QPainter(self)
p.drawPixmap(QtCore.QPoint(l, self.renderer.height-t), pixmap)
p.end()
self.blitbox = None
self.drawRect = False

def draw(self):
"""
Draw the figure with Agg, and queue a request
for a Qt draw.
"""
# The Agg draw is done here; delaying it until the paintEvent
# causes problems with code that uses the result of the
# draw() to update plot elements.
FigureCanvasAgg.draw(self)
self.update()

def blit(self, bbox=None):
"""
Blit the region in bbox
"""
self.blitbox = bbox
l, b, w, h = bbox.bounds
t = b + h
self.repaint(l, self.renderer.height-t, w, h)

def print_figure(self, *args, **kwargs):
FigureCanvasAgg.print_figure(self, *args, **kwargs)
self.draw()
168 changes: 15 additions & 153 deletions lib/matplotlib/backends/backend_qt4agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,169 +5,31 @@
unicode_literals)

import six

import os # not used
import sys
import ctypes
import warnings

import matplotlib
from matplotlib.figure import Figure

from .backend_agg import FigureCanvasAgg
from .backend_qt4 import QtCore
from .backend_qt4 import QtGui
from .backend_qt4 import FigureManagerQT
from .backend_qt4 import FigureCanvasQT
from .backend_qt4 import NavigationToolbar2QT
##### not used
from .backend_qt4 import show
from .backend_qt4 import draw_if_interactive
from .backend_qt4 import backend_version
######
from matplotlib.cbook import mplDeprecation

DEBUG = False

_decref = ctypes.pythonapi.Py_DecRef
_decref.argtypes = [ctypes.py_object]
_decref.restype = None


def new_figure_manager(num, *args, **kwargs):
"""
Create a new figure manager instance
"""
if DEBUG:
print('backend_qtagg.new_figure_manager')
FigureClass = kwargs.pop('FigureClass', Figure)
thisFig = FigureClass(*args, **kwargs)
return new_figure_manager_given_figure(num, thisFig)


def new_figure_manager_given_figure(num, figure):
"""
Create a new figure manager instance for the given figure.
"""
canvas = FigureCanvasQTAgg(figure)
return FigureManagerQT(canvas, num)

# import Gcf/pyplot stuff
from matplotlib._pylab_helpers import Gcf

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.blitbox = None
self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)

def drawRectangle(self, rect):
self.rect = rect
self.drawRect = True
self.repaint()

def paintEvent(self, e):
"""
Copy the image from the Agg canvas to the qt.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,
self.get_width_height())

if self.blitbox is None:
# 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).
if QtCore.QSysInfo.ByteOrder == QtCore.QSysInfo.LittleEndian:
stringBuffer = self.renderer._renderer.tostring_bgra()
else:
stringBuffer = self.renderer._renderer.tostring_argb()

refcnt = sys.getrefcount(stringBuffer)

# convert the Agg rendered image -> qImage
qImage = QtGui.QImage(stringBuffer, self.renderer.width,
self.renderer.height,
QtGui.QImage.Format_ARGB32)
# get the rectangle for the image
rect = qImage.rect()
p = QtGui.QPainter(self)
# reset the image area of the canvas to be the back-ground color
p.eraseRect(rect)
# draw the rendered image on to the canvas
p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage))
# import Gcf stuff from QT4 backend
from .backend_qt4 import show
from .backend_qt4 import draw_if_interactive

# 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()
# import the backend with call backs included from
from .backend_qt4 import FigureManagerQT

# This works around a bug in PySide 1.1.2 on Python 3.x,
# where the reference count of stringBuffer is incremented
# but never decremented by QImage.
# TODO: revert PR #1323 once the issue is fixed in PySide.
del qImage
if refcnt != sys.getrefcount(stringBuffer):
_decref(stringBuffer)
else:
bbox = self.blitbox
l, b, r, t = bbox.extents
w = int(r) - int(l)
h = int(t) - int(b)
t = int(b) + h
reg = self.copy_from_bbox(bbox)
stringBuffer = reg.to_string_argb()
qImage = QtGui.QImage(stringBuffer, w, h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
p = QtGui.QPainter(self)
p.drawPixmap(QtCore.QPoint(l, self.renderer.height-t), pixmap)
p.end()
self.blitbox = None
self.drawRect = False

def draw(self):
"""
Draw the figure with Agg, and queue a request
for a Qt draw.
"""
# The Agg draw is done here; delaying it until the paintEvent
# causes problems with code that uses the result of the
# draw() to update plot elements.
FigureCanvasAgg.draw(self)
self.update()
from ._backend_qt4 import (TimerQT,
SubplotToolQt,
backend_version)

def blit(self, bbox=None):
"""
Blit the region in bbox
"""
self.blitbox = bbox
l, b, w, h = bbox.bounds
t = b + h
self.repaint(l, self.renderer.height-t, w, h)

def print_figure(self, *args, **kwargs):
FigureCanvasAgg.print_figure(self, *args, **kwargs)
self.draw()
# import qtAgg stuff
from ._backend_qt4agg import (new_figure_manager,
new_figure_manager_given_figure,
NavigationToolbar2QT,
FigureCanvasQTAgg)


class NavigationToolbar2QTAgg(NavigationToolbar2QT):
Expand Down
0