| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,7 @@ | |||
| 1 | + Blitting in Button widgets | ||
| 2 | + -------------------------- | ||
| 3 | + | ||
| 4 | + The `.Button`, `.CheckButtons`, and `.RadioButtons` widgets now support | ||
| 5 | + blitting for faster rendering, on backends that support it, by passing | ||
| 6 | + ``useblit=True`` to the constructor. Blitting is enabled by default on | ||
| 7 | + supported backends. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -152,7 +152,7 @@ class Button(AxesWidget): | |||
| 152 | 152 | """ | |
| 153 | 153 | ||
| 154 | 154 | def __init__(self, ax, label, image=None, | |
| 155 | - color='0.85', hovercolor='0.95'): | ||
| 155 | + color='0.85', hovercolor='0.95', *, useblit=True): | ||
| 156 | 156 | """ | |
| 157 | 157 | Parameters | |
| 158 | 158 | ---------- | |
@@ -167,6 +167,9 @@ def __init__(self, ax, label, image=None, | |||
| 167 | 167 | The color of the button when not activated. | |
| 168 | 168 | hovercolor : color | |
| 169 | 169 | The color of the button when the mouse is over it. | |
| 170 | + useblit : bool, default: True | ||
| 171 | + Use blitting for faster drawing if supported by the backend. | ||
| 172 | + See the tutorial :doc:`/tutorials/advanced/blitting` for details. | ||
| 170 | 173 | """ | |
| 171 | 174 | super().__init__(ax) | |
| 172 | 175 | ||
@@ -177,6 +180,8 @@ def __init__(self, ax, label, image=None, | |||
| 177 | 180 | horizontalalignment='center', | |
| 178 | 181 | transform=ax.transAxes) | |
| 179 | 182 | ||
| 183 | + self._useblit = useblit and self.canvas.supports_blit | ||
| 184 | + | ||
| 180 | 185 | self._observers = cbook.CallbackRegistry(signals=["clicked"]) | |
| 181 | 186 | ||
| 182 | 187 | self.connect_event('button_press_event', self._click) | |
@@ -209,7 +214,11 @@ def _motion(self, event): | |||
| 209 | 214 | if not colors.same_color(c, self.ax.get_facecolor()): | |
| 210 | 215 | self.ax.set_facecolor(c) | |
| 211 | 216 | if self.drawon: | |
| 212 | - self.ax.figure.canvas.draw() | ||
| 217 | + if self._useblit: | ||
| 218 | + self.ax.draw_artist(self.ax) | ||
| 219 | + self.canvas.blit(self.ax.bbox) | ||
| 220 | + else: | ||
| 221 | + self.canvas.draw() | ||
| 213 | 222 | ||
| 214 | 223 | def on_clicked(self, func): | |
| 215 | 224 | """ | |
@@ -968,6 +977,7 @@ class CheckButtons(AxesWidget): | |||
| 968 | 977 | ---------- | |
| 969 | 978 | ax : `~matplotlib.axes.Axes` | |
| 970 | 979 | The parent Axes for the widget. | |
| 980 | + | ||
| 971 | 981 | labels : list of `.Text` | |
| 972 | 982 | ||
| 973 | 983 | rectangles : list of `.Rectangle` | |
@@ -977,21 +987,22 @@ class CheckButtons(AxesWidget): | |||
| 977 | 987 | each box, but have ``set_visible(False)`` when its box is not checked. | |
| 978 | 988 | """ | |
| 979 | 989 | ||
| 980 | - def __init__(self, ax, labels, actives=None): | ||
| 990 | + def __init__(self, ax, labels, actives=None, *, useblit=True): | ||
| 981 | 991 | """ | |
| 982 | 992 | Add check buttons to `matplotlib.axes.Axes` instance *ax*. | |
| 983 | 993 | ||
| 984 | 994 | Parameters | |
| 985 | 995 | ---------- | |
| 986 | 996 | ax : `~matplotlib.axes.Axes` | |
| 987 | 997 | The parent Axes for the widget. | |
| 988 | - | ||
| 989 | 998 | labels : list of str | |
| 990 | 999 | The labels of the check buttons. | |
| 991 | - | ||
| 992 | 1000 | actives : list of bool, optional | |
| 993 | 1001 | The initial check states of the buttons. The list must have the | |
| 994 | 1002 | same length as *labels*. If not given, all buttons are unchecked. | |
| 1003 | + useblit : bool, default: True | ||
| 1004 | + Use blitting for faster drawing if supported by the backend. | ||
| 1005 | + See the tutorial :doc:`/tutorials/advanced/blitting` for details. | ||
| 995 | 1006 | """ | |
| 996 | 1007 | super().__init__(ax) | |
| 997 | 1008 | ||
@@ -1002,6 +1013,9 @@ def __init__(self, ax, labels, actives=None): | |||
| 1002 | 1013 | if actives is None: | |
| 1003 | 1014 | actives = [False] * len(labels) | |
| 1004 | 1015 | ||
| 1016 | + self._useblit = useblit and self.canvas.supports_blit | ||
| 1017 | + self._background = None | ||
| 1018 | + | ||
| 1005 | 1019 | ys = np.linspace(1, 0, len(labels)+2)[1:-1] | |
| 1006 | 1020 | text_size = mpl.rcParams["font.size"] / 2 | |
| 1007 | 1021 | ||
@@ -1017,13 +1031,26 @@ def __init__(self, ax, labels, actives=None): | |||
| 1017 | 1031 | self._crosses = ax.scatter( | |
| 1018 | 1032 | [0.15] * len(ys), ys, marker='x', linewidth=1, s=text_size**2, | |
| 1019 | 1033 | c=["k" if active else "none" for active in actives], | |
| 1020 | - transform=ax.transAxes | ||
| 1034 | + transform=ax.transAxes, animated=self._useblit, | ||
| 1021 | 1035 | ) | |
| 1022 | 1036 | ||
| 1023 | 1037 | self.connect_event('button_press_event', self._clicked) | |
| 1038 | + if self._useblit: | ||
| 1039 | + self.connect_event('draw_event', self._clear) | ||
| 1024 | 1040 | ||
| 1025 | 1041 | self._observers = cbook.CallbackRegistry(signals=["clicked"]) | |
| 1026 | 1042 | ||
| 1043 | + def _clear(self, event): | ||
| 1044 | + """Internal event handler to clear the buttons.""" | ||
| 1045 | + if self.ignore(event): | ||
| 1046 | + return | ||
| 1047 | + self._background = self.canvas.copy_from_bbox(self.ax.bbox) | ||
| 1048 | + self.ax.draw_artist(self._crosses) | ||
| 1049 | + if hasattr(self, '_lines'): | ||
| 1050 | + for l1, l2 in self._lines: | ||
| 1051 | + self.ax.draw_artist(l1) | ||
| 1052 | + self.ax.draw_artist(l2) | ||
| 1053 | + | ||
| 1027 | 1054 | def _clicked(self, event): | |
| 1028 | 1055 | if self.ignore(event) or event.button != 1 or event.inaxes != self.ax: | |
| 1029 | 1056 | return | |
@@ -1084,7 +1111,17 @@ def set_active(self, index): | |||
| 1084 | 1111 | l2.set_visible(not l2.get_visible()) | |
| 1085 | 1112 | ||
| 1086 | 1113 | if self.drawon: | |
| 1087 | - self.ax.figure.canvas.draw() | ||
| 1114 | + if self._useblit: | ||
| 1115 | + if self._background is not None: | ||
| 1116 | + self.canvas.restore_region(self._background) | ||
| 1117 | + self.ax.draw_artist(self._crosses) | ||
| 1118 | + if hasattr(self, "_lines"): | ||
| 1119 | + for l1, l2 in self._lines: | ||
| 1120 | + self.ax.draw_artist(l1) | ||
| 1121 | + self.ax.draw_artist(l2) | ||
| 1122 | + self.canvas.blit(self.ax.bbox) | ||
| 1123 | + else: | ||
| 1124 | + self.canvas.draw() | ||
| 1088 | 1125 | ||
| 1089 | 1126 | if self.eventson: | |
| 1090 | 1127 | self._observers.process('clicked', self.labels[index].get_text()) | |
@@ -1143,7 +1180,8 @@ def lines(self): | |||
| 1143 | 1180 | current_status = self.get_status() | |
| 1144 | 1181 | lineparams = {'color': 'k', 'linewidth': 1.25, | |
| 1145 | 1182 | 'transform': self.ax.transAxes, | |
| 1146 | - 'solid_capstyle': 'butt'} | ||
| 1183 | + 'solid_capstyle': 'butt', | ||
| 1184 | + 'animated': self._useblit} | ||
| 1147 | 1185 | for i, y in enumerate(ys): | |
| 1148 | 1186 | x, y = 0.05, y - h / 2 | |
| 1149 | 1187 | l1 = Line2D([x, x + w], [y + h, y], **lineparams) | |
@@ -1447,7 +1485,8 @@ class RadioButtons(AxesWidget): | |||
| 1447 | 1485 | The label text of the currently selected button. | |
| 1448 | 1486 | """ | |
| 1449 | 1487 | ||
| 1450 | - def __init__(self, ax, labels, active=0, activecolor='blue'): | ||
| 1488 | + def __init__(self, ax, labels, active=0, activecolor='blue', *, | ||
| 1489 | + useblit=True): | ||
| 1451 | 1490 | """ | |
| 1452 | 1491 | Add radio buttons to an `~.axes.Axes`. | |
| 1453 | 1492 | ||
@@ -1461,6 +1500,9 @@ def __init__(self, ax, labels, active=0, activecolor='blue'): | |||
| 1461 | 1500 | The index of the initially selected button. | |
| 1462 | 1501 | activecolor : color | |
| 1463 | 1502 | The color of the selected button. | |
| 1503 | + useblit : bool, default: True | ||
| 1504 | + Use blitting for faster drawing if supported by the backend. | ||
| 1505 | + See the tutorial :doc:`/tutorials/advanced/blitting` for details. | ||
| 1464 | 1506 | """ | |
| 1465 | 1507 | super().__init__(ax) | |
| 1466 | 1508 | self.activecolor = activecolor | |
@@ -1473,19 +1515,34 @@ def __init__(self, ax, labels, active=0, activecolor='blue'): | |||
| 1473 | 1515 | ys = np.linspace(1, 0, len(labels) + 2)[1:-1] | |
| 1474 | 1516 | text_size = mpl.rcParams["font.size"] / 2 | |
| 1475 | 1517 | ||
| 1518 | + self._useblit = useblit and self.canvas.supports_blit | ||
| 1519 | + self._background = None | ||
| 1520 | + | ||
| 1476 | 1521 | self.labels = [ | |
| 1477 | 1522 | ax.text(0.25, y, label, transform=ax.transAxes, | |
| 1478 | 1523 | horizontalalignment="left", verticalalignment="center") | |
| 1479 | 1524 | for y, label in zip(ys, labels)] | |
| 1480 | 1525 | self._buttons = ax.scatter( | |
| 1481 | 1526 | [.15] * len(ys), ys, transform=ax.transAxes, s=text_size**2, | |
| 1482 | 1527 | c=[activecolor if i == active else "none" for i in range(len(ys))], | |
| 1483 | - edgecolor="black") | ||
| 1528 | + edgecolor="black", animated=self._useblit) | ||
| 1484 | 1529 | ||
| 1485 | 1530 | self.connect_event('button_press_event', self._clicked) | |
| 1531 | + if self._useblit: | ||
| 1532 | + self.connect_event('draw_event', self._clear) | ||
| 1486 | 1533 | ||
| 1487 | 1534 | self._observers = cbook.CallbackRegistry(signals=["clicked"]) | |
| 1488 | 1535 | ||
| 1536 | + def _clear(self, event): | ||
| 1537 | + """Internal event handler to clear the buttons.""" | ||
| 1538 | + if self.ignore(event): | ||
| 1539 | + return | ||
| 1540 | + self._background = self.canvas.copy_from_bbox(self.ax.bbox) | ||
| 1541 | + self.ax.draw_artist(self._buttons) | ||
| 1542 | + if hasattr(self, "_circles"): | ||
| 1543 | + for circle in self._circles: | ||
| 1544 | + self.ax.draw_artist(circle) | ||
| 1545 | + | ||
| 1489 | 1546 | def _clicked(self, event): | |
| 1490 | 1547 | if self.ignore(event) or event.button != 1 or event.inaxes != self.ax: | |
| 1491 | 1548 | return | |
@@ -1524,8 +1581,20 @@ def set_active(self, index): | |||
| 1524 | 1581 | if hasattr(self, "_circles"): # Remove once circles is removed. | |
| 1525 | 1582 | for i, p in enumerate(self._circles): | |
| 1526 | 1583 | p.set_facecolor(self.activecolor if i == index else "none") | |
| 1584 | + if self.drawon and self._useblit: | ||
| 1585 | + self.ax.draw_artist(p) | ||
| 1527 | 1586 | if self.drawon: | |
| 1528 | - self.ax.figure.canvas.draw() | ||
| 1587 | + if self._useblit: | ||
| 1588 | + if self._background is not None: | ||
| 1589 | + self.canvas.restore_region(self._background) | ||
| 1590 | + self.ax.draw_artist(self._buttons) | ||
| 1591 | + if hasattr(self, "_circles"): | ||
| 1592 | + for p in self._circles: | ||
| 1593 | + self.ax.draw_artist(p) | ||
| 1594 | + self.canvas.blit(self.ax.bbox) | ||
| 1595 | + else: | ||
| 1596 | + self.canvas.draw() | ||
| 1597 | + | ||
| 1529 | 1598 | if self.eventson: | |
| 1530 | 1599 | self._observers.process('clicked', self.labels[index].get_text()) | |
| 1531 | 1600 | ||
@@ -1549,7 +1618,8 @@ def circles(self): | |||
| 1549 | 1618 | circles = self._circles = [ | |
| 1550 | 1619 | Circle(xy=self._buttons.get_offsets()[i], edgecolor="black", | |
| 1551 | 1620 | facecolor=self._buttons.get_facecolor()[i], | |
| 1552 | - radius=radius, transform=self.ax.transAxes) | ||
| 1621 | + radius=radius, transform=self.ax.transAxes, | ||
| 1622 | + animated=self._useblit) | ||
| 1553 | 1623 | for i in range(len(self.labels))] | |
| 1554 | 1624 | self._buttons.set_visible(False) | |
| 1555 | 1625 | for circle in circles: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments