PyQt5:从 QTextEdit 复制图像并粘贴到油漆中
我试图允许我的文本编辑将图像从 QTextEdit 复制并粘贴到 Microsoft Paint。
目前我有一个自定义文本编辑,允许我将图像粘贴到文本编辑中。我将整个文档保存为 HTML 并稍后重新加载,因此当我粘贴图像时,我使用
其中二进制是调整大小的 Base64 二进制图像。这样,图像二进制文件就会嵌入到 HTML 中,我不需要跟踪任何源图像。
这是我的 QTextEdit 的代码,允许进行粘贴。
class TextEdit(QTextEdit):
def __init__(self):
super().__init__()
self.setMaximumWidth(800)
self.setStyleSheet("background-color: rgb(255, 255, 255);")
def canInsertFromMimeData(self, source):
if source.hasImage():
return True
else:
return super(TextEdit, self).canInsertFromMimeData(source)
def insertFromMimeData(self, source):
cursor = self.textCursor()
document = self.document()
if source.hasUrls():
for u in source.urls():
file_ext = os.path.splitext(str(u.toLocalFile()))[1].lower()
if u.isLocalFile() and file_ext in IMAGE_EXTENSIONS:
img = Image.open(u.toLocalFile())
width, height = img.size
max_width = int(document.pageSize().width())
max_height = int(max_width * height / width)
if width > max_width or height > max_height:
img = img.resize((max_width, max_height), Image.ANTIALIAS)
output = io.BytesIO()
img.save(output, format=file_ext.replace(".",""), quality=3000)
binary = str(base64.b64encode(output.getvalue()))
binary = binary.replace("b'", "")
binary = binary.replace("'", "")
HTMLBin = "<img src= \"data:image/*;base64," + binary + "\" max-width=100% max-height=100%/>"
cursor.insertHtml(HTMLBin)
return
else:
# If we hit a non-image or non-local URL break the loop and fall out
# to the super call & let Qt handle it
break
else:
# If all were valid images, finish here.
return
elif source.hasImage():
img = source.imageData()
#Save the image from the clipboard into a buffer
ba = QtCore.QByteArray()
buffer = QtCore.QBuffer(ba)
buffer.open(QtCore.QIODevice.WriteOnly)
img.save(buffer, 'PNG')
#Load the image binary into PIL.Image (Python Image Library)
img = Image.open(io.BytesIO(ba.data()))
#Find what the max size of the document is.
width, height = img.size
max_width = 775
max_height = int(max_width * height / width)
#Resize to make sure the image fits in the document.
if (width > max_width or height > max_height) and (max_width!=0 and max_height!=0):
img = img.resize((max_width, max_height), Image.ANTIALIAS)
#Convert binary into a string representation of the base64 to embed the image into the HTML
output = io.BytesIO()
img.save(output, format='PNG', quality=95)
binary = str(base64.b64encode(output.getvalue()))
# base64_data = ba.toBase64().data()
# binary = str(base64_data)
binary = binary.replace("b'", "")
binary = binary.replace("'", "")
#Write the HTML and insert it at the Document Cursor.
HTMLBin = "<img src= \"data:image/*;base64," + binary + "\" max-width=100% max-height=100%> </img>"
cursor.insertHtml(HTMLBin)
return
elif source.hasHtml():
html = source.html()
cursor.insertHtml(html)
return
super(TextEdit, self).insertFromMimeData(source)
现在我需要做的是,当再次复制图像时,我基本上需要删除二进制文件周围的 HTML img 标签并仅复制二进制文件。
我尝试重载 QTextEdit.copy() 方法,该方法似乎没有执行任何操作,并且我尝试覆盖 QTextEdit.createMimeDataFromSelection() 但我无法找到一种方法让副本像以前一样工作一旦我这样做了。
有人知道如何实现这一目标吗?我希望解决方案位于我的自定义 QTextEdit 中,而不是在该类之外完成,这样我就可以在其他项目的其他地方重复使用相同的功能。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了将图像复制到剪贴板,您必须首先确保所选内容仅包含一个图像而没有其他内容:没有文本,也没有其他图像。
考虑到图像在文本文档中仅占据一个字符(用作图像对象的“占位符”),可以检查选择的长度是否实际上为1,然后验证末尾的字符格式 的选择是 QTextImageFormat,这是一种特殊类型QTextFormat 用于图像;选择末尾的位置至关重要,因为格式始终被考虑在光标左侧。
通过覆盖
createMimeDataFromSelection
并执行上述操作,您可以轻松返回包含从文档资源加载的图像的 QMimeData。请注意,从剪贴板添加图像的更好(也更简单)的方法是使用现有的 Qt 功能,这样您就可以避免通过 PIL 进行不必要的转换并传递两个数据缓冲区。
请注意,我使用正确的 类选择器更改了样式表:这非常非常重要,因为为复杂的小部件(最重要的是滚动区域)设置通用属性可能会产生图形问题,因为它们会传播到所有子部件该小部件,包括滚动条(某些样式会变得丑陋)、上下文菜单和模式对话框。
In order to copy an image to the clipboard, you have to first ensure that the selection only contains one image and nothing else: no text and no other images.
Considering that images occupy only one character in the text document (used as a "placeholder" for the image object), you can check if the length of the selection is actually 1, and then verify that the character format at the end of the selection is a QTextImageFormat, which is a special type of QTextFormat used for images; the position at the end of the selection is fundamental, as formats are always considered at the left of the cursor.
By overriding
createMimeDataFromSelection
and doing the above you can easily return a QMimeData that contains the image loaded from the document's resources.Note that a better (and simpler) approach to add images from the clipboard is to use the existing Qt features, so that you can avoid an unnecessary conversion through PIL and passing through two data buffers.
Note that I changed the stylesheet with a proper class selector: this is very important as setting generic properties for complex widgets (most importantly, scroll areas) can create graphical issues, as they are propagated to all children of that widget, including scroll bars (which become ugly with certain styles), context menus and modal dialogs.