7
7
import six
8
8
9
9
import ctypes
10
+ from threading import Lock
10
11
import traceback
11
12
12
13
from matplotlib import cbook
@@ -34,9 +35,14 @@ class FigureCanvasQTAggBase(FigureCanvasAgg):
34
35
def __init__ (self , figure ):
35
36
super (FigureCanvasQTAggBase , self ).__init__ (figure = figure )
36
37
self .setAttribute (QtCore .Qt .WA_OpaquePaintEvent )
38
+ self ._drawRect = None
37
39
self ._agg_draw_pending = False
40
+ # A list of Bboxes that will be repainted in the next paintEvent. As a
41
+ # special case, an entry set to None requests the canvas to be fully
42
+ # erased.
38
43
self ._bbox_queue = []
39
- self ._drawRect = None
44
+ # A mutex to protect all changes to _bbox_queue.
45
+ self ._bbox_queue_lock = Lock ()
40
46
41
47
def drawRectangle (self , rect ):
42
48
if rect is not None :
@@ -48,7 +54,7 @@ def drawRectangle(self, rect):
48
54
@property
49
55
@cbook .deprecated ("2.1" )
50
56
def blitbox (self ):
51
- return self ._bbox_queue
57
+ return [ bbox for bbox in self ._bbox_queue if bbox is not None ]
52
58
53
59
def paintEvent (self , e ):
54
60
"""Copy the image from the Agg canvas to the qt.drawable.
@@ -62,30 +68,30 @@ def paintEvent(self, e):
62
68
return
63
69
64
70
painter = QtGui .QPainter (self )
65
-
66
- if self ._bbox_queue :
71
+ with self ._bbox_queue_lock :
67
72
bbox_queue = self ._bbox_queue
68
- else :
69
- painter .eraseRect (self .rect ())
70
- bbox_queue = [
71
- Bbox ([[0 , 0 ], [self .renderer .width , self .renderer .height ]])]
73
+ self ._bbox_queue = []
74
+
72
75
self ._bbox_queue = []
73
76
for bbox in bbox_queue :
74
- l , b , r , t = map (int , bbox .extents )
75
- w = r - l
76
- h = t - b
77
- reg = self .copy_from_bbox (bbox )
78
- buf = reg .to_string_argb ()
79
- qimage = QtGui .QImage (buf , w , h , QtGui .QImage .Format_ARGB32 )
80
- if hasattr (qimage , 'setDevicePixelRatio' ):
81
- # Not available on Qt4 or some older Qt5.
82
- qimage .setDevicePixelRatio (self ._dpi_ratio )
83
- origin = QtCore .QPoint (l , self .renderer .height - t )
84
- painter .drawImage (origin / self ._dpi_ratio , qimage )
85
- # Adjust the buf reference count to work around a memory
86
- # leak bug in QImage under PySide on Python 3.
87
- if QT_API == 'PySide' and six .PY3 :
88
- ctypes .c_long .from_address (id (buf )).value = 1
77
+ if bbox is None :
78
+ painter .eraseRect (self .rect ())
79
+ else :
80
+ l , b , r , t = map (int , bbox .extents )
81
+ w = r - l
82
+ h = t - b
83
+ reg = self .copy_from_bbox (bbox )
84
+ buf = reg .to_string_argb ()
85
+ qimage = QtGui .QImage (buf , w , h , QtGui .QImage .Format_ARGB32 )
86
+ if hasattr (qimage , 'setDevicePixelRatio' ):
87
+ # Not available on Qt4 or some older Qt5.
88
+ qimage .setDevicePixelRatio (self ._dpi_ratio )
89
+ origin = QtCore .QPoint (l , self .renderer .height - t )
90
+ painter .drawImage (origin / self ._dpi_ratio , qimage )
91
+ # Adjust the buf reference count to work around a memory
92
+ # leak bug in QImage under PySide on Python 3.
93
+ if QT_API == 'PySide' and six .PY3 :
94
+ ctypes .c_long .from_address (id (buf )).value = 1
89
95
90
96
# draw the zoom rectangle to the QPainter
91
97
if self ._drawRect is not None :
@@ -103,6 +109,11 @@ def draw(self):
103
109
# The Agg draw is done here; delaying causes problems with code that
104
110
# uses the result of the draw() to update plot elements.
105
111
super (FigureCanvasQTAggBase , self ).draw ()
112
+ with self ._bbox_queue_lock :
113
+ # Erase the canvas and repaint everything.
114
+ self ._bbox_queue = [
115
+ None ,
116
+ Bbox ([[0 , 0 ], [self .renderer .width , self .renderer .height ]])]
106
117
self .update ()
107
118
108
119
def draw_idle (self ):
@@ -137,7 +148,8 @@ def blit(self, bbox=None):
137
148
if bbox is None and self .figure :
138
149
bbox = self .figure .bbox
139
150
140
- self ._bbox_queue .append (bbox )
151
+ with self ._bbox_queue_lock :
152
+ self ._bbox_queue .append (bbox )
141
153
142
154
# repaint uses logical pixels, not physical pixels like the renderer.
143
155
l , b , w , h = [pt / self ._dpi_ratio for pt in bbox .bounds ]
0 commit comments