|
| 1 | +import io |
1 | 2 | from functools import partial |
2 | 3 |
|
3 | 4 | from PySide6 import QtCore, QtGui |
@@ -182,22 +183,60 @@ def saveImage(self, filename): |
182 | 183 |
|
183 | 184 | def copyImageToClipboard(self): |
184 | 185 | """Copy the current canvas image to the clipboard.""" |
185 | | - self.draw() |
186 | | - width, height = self.get_width_height() |
187 | | - if width <= 0 or height <= 0: |
| 186 | + image = self._export_plot_image() |
| 187 | + if image is None: |
188 | 188 | return False |
189 | 189 |
|
190 | | - image = QtGui.QImage(self.buffer_rgba(), |
191 | | - width, |
192 | | - height, |
193 | | - QtGui.QImage.Format_RGBA8888).copy() |
194 | | - pixmap = QtGui.QPixmap.fromImage(image) |
195 | | - if pixmap.isNull(): |
| 190 | + clipboard = QtGui.QGuiApplication.clipboard() |
| 191 | + if clipboard is None: |
196 | 192 | return False |
197 | 193 |
|
198 | | - QtGui.QGuiApplication.clipboard().setPixmap(pixmap) |
| 194 | + clipboard.setImage(image) |
199 | 195 | return True |
200 | 196 |
|
| 197 | + def _export_plot_image(self): |
| 198 | + self.draw() |
| 199 | + width, height = self.get_width_height() |
| 200 | + if width <= 0 or height <= 0: |
| 201 | + return None |
| 202 | + |
| 203 | + buffer = io.BytesIO() |
| 204 | + self.figure.savefig(buffer, |
| 205 | + format='png', |
| 206 | + transparent=True) |
| 207 | + image = QtGui.QImage.fromData(buffer.getvalue(), 'PNG') |
| 208 | + if image.isNull(): |
| 209 | + return None |
| 210 | + |
| 211 | + crop_rect = self._visible_canvas_rect(image.width(), image.height()) |
| 212 | + if crop_rect.isEmpty(): |
| 213 | + return None |
| 214 | + |
| 215 | + return image.copy(crop_rect) |
| 216 | + |
| 217 | + def _visible_canvas_rect(self, image_width, image_height): |
| 218 | + if self.width() <= 0 or self.height() <= 0: |
| 219 | + return QtCore.QRect() |
| 220 | + |
| 221 | + if self.parent is None or not hasattr(self.parent, 'viewport'): |
| 222 | + return QtCore.QRect(0, 0, image_width, image_height) |
| 223 | + |
| 224 | + viewport = self.parent.viewport() |
| 225 | + visible_width = min(viewport.width(), self.width()) |
| 226 | + visible_height = min(viewport.height(), self.height()) |
| 227 | + x_offset = self.parent.horizontalScrollBar().value() |
| 228 | + y_offset = self.parent.verticalScrollBar().value() |
| 229 | + |
| 230 | + scale_x = image_width / self.width() |
| 231 | + scale_y = image_height / self.height() |
| 232 | + |
| 233 | + return QtCore.QRect(round(x_offset * scale_x), |
| 234 | + round(y_offset * scale_y), |
| 235 | + round(visible_width * scale_x), |
| 236 | + round(visible_height * scale_y)).intersected( |
| 237 | + QtCore.QRect(0, 0, image_width, image_height) |
| 238 | + ) |
| 239 | + |
201 | 240 | def getDataIndices(self, event): |
202 | 241 | cv = self.model.currentView |
203 | 242 |
|
|
0 commit comments