[英]Embed Pyqtgraph into Pyqt Textedit
I'd like to create a text editor where you can drag and drop Pyqtgraphs and interact with them real-time.我想创建一个文本编辑器,您可以在其中拖放 Pyqtgraphs 并与它们实时交互。 I am having trouble understanding the behavior of TextEdit and how a Widget could be 'embedded' within the TextEdit itself.
我无法理解 TextEdit 的行为以及如何将小部件“嵌入”到 TextEdit 本身中。 After review the API it seems that only text, html, and images can be added into the QTextEdit.
查看 API 后,似乎只能将文本、html 和图像添加到 QTextEdit 中。
I might be grasping at straws here, but I was hoping that there was a void QTextEdit::insertWidget(QWidget*)
or something of that nature.我可能在这里抓住了稻草,但我希望有一个
void QTextEdit::insertWidget(QWidget*)
或类似的东西。
To clarify here is an incomplete sample code:澄清这里是一个不完整的示例代码:
import sys
import numpy as np
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import pyqtgraph as pg
class PlotTextEditor(QMainWindow):
def __init__(self):
super().__init__()
self.textEdit = QTextEdit(self)
self.setCentralWidget(self.textEdit)
toolbar = QToolBar()
plotAction = QAction('Plot', self)
plotAction.triggered.connect(self.addPlot)
toolbar.addAction(plotAction)
self.addToolBar(toolbar)
self.setGeometry(300, 100, 800, 1000)
def addPlot(self):
x = np.linspace(0, 10, 100)
y = np.sin(x)
glWidget = pg.GraphicsLayoutWidget()
plot = glWidget.addPlot()
plot.plot(x, y, pen='r')
# I'd like to be able to use a line such as this
# self.textEdit.textCursor().insertWidget(glWidget)
self.textEdit.textCursor().insertText('I want to insert a widget pointer instead.')
if __name__ == "__main__":
app = QApplication(sys.argv)
pte = PlotTextEditor()
pte.show()
sys.exit(app.exec_())
Some ideas I had were to overlay the pyqtgraph over a blank image, or try to find some kind of text widget I can insert and override paintevent to give it the pyqtgraph paint.我的一些想法是将 pyqtgraph 覆盖在空白图像上,或者尝试找到某种文本小部件,我可以插入并覆盖 Paintevent 以赋予它 pyqtgraph 绘制。 Ultimately however, I am not sure if this is even possible with the current Qt backend with TextEdit.
然而,最终,我不确定当前的 Qt 后端是否可以使用 TextEdit。
Please try this Code.请试试这个代码。
If you want to further information , please ask me by comment.如果您想了解更多信息,请通过评论问我。 I don't know if you like this result or not.
不知道你们喜不喜欢这个结果。
UPDATE TRANSITION更新过渡
plot image can be rendered but the data is not rendered.可以渲染绘图图像,但不渲染数据。 I changed
pen = 'r': plot.plot(x, y, pen)
to plot.plot(x, y, pen = 'r')
我改变了
pen = 'r': plot.plot(x, y, pen)
到plot.plot(x, y, pen = 'r')
the data of plot image is dirty and not antialiased, intercepted on and off.绘图图像的数据是脏的,没有抗锯齿,断断续续地截取。 I update
intrinsicSize()
and return image width and image height, You can look a bad result if you set return QSizeF()
argument in intrinsicSize
as you like.我更新了
intrinsicSize()
并返回图像宽度和图像高度,如果您根据return QSizeF()
在intrinsicSize
设置return QSizeF()
参数,您可能会看到一个糟糕的结果。
Interactively as possible as we can.尽可能互动。 As you can see, this image is drawn by
QPainter
.如您所见,此图像是由
QPainter
绘制的。 So , originally, this is uninteractive.I think this is the only way for rendering your result as QTextObject
.所以,最初,这是非交互式的。我认为这是将结果呈现为
QTextObject
的唯一方法。 QTextEdit
can't accept a kind of widgets as text. QTextEdit
不能接受一种小部件作为文本。
Please click in front of the image.请点击图片前面的。
GraphicsLayoutWidget
shows.and you change the graph contents, and you close it. GraphicsLayoutWidget
显示。您更改图形内容,然后关闭它。 And the next time, the image is redrawn and rendered again.下一次,图像被重新绘制和渲染。
I deleted needless code.我删除了不必要的代码。
Anyway, I tried to do until this point.不管怎样,我一直努力做到这一点。
Please ask me about further imformation by comment.请通过评论向我询问更多信息。
import sys
import numpy as np
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import pyqtgraph as pg
import pyqtgraph.exporters
import os
plot_image_dict = {}
class PlotObjectInterface(QObject, QTextObjectInterface):
def __init__(self, parent=None):
super(PlotObjectInterface, self).__init__(parent=None)
def drawObject(self, painter, rect, doc, posInDocument, format):
img = format.property(1)
painter.save()
painter.setRenderHints(QPainter.Antialiasing)
painter.drawImage(QRectF(rect), img)
painter.restore()
def intrinsicSize(self, doc, posInDocument, format):
img = format.property(1)
width = img.size().width()
height = img.size().height()
return QSizeF(width, height)
class PlotTextEdit(QTextEdit):
def __init__(self):
super().__init__()
class PlotView(QGraphicsView):
def __init__(self):
super().__init__()
self.plot_scene = QGraphicsScene()
self.plot_tedit = PlotTextEdit()
self.plot_tedit.resize(800, 1000)
self.plot_scene.addWidget(self.plot_tedit)
self.setScene(self.plot_scene)
class PlotGraphicsLayoutWidget(pg.GraphicsLayoutWidget):
def __init__(self):
super().__init__()
self.current_edit_filename = ""
self.current_edit_imagenum = 0
self.current_edit_image = QImage()
self.current_edit_position = 0
def updateImage(self):
#overwrite the image
pg.QtGui.QApplication.processEvents()
exporter = pg.exporters.ImageExporter(self.scene())
filename = os.path.join(self.current_edit_filename)
exporter.export(filename)
image = QImage()
image.load(filename)
image_info = plot_image_dict[self.current_edit_imagenum]
tc = QTextCursor(self.current_text_edit.document())
tc.setPosition(image_info[3] - 1, tc.MoveAnchor)
tc.movePosition(tc.Right, tc.KeepAnchor, 1)
tc.setKeepPositionOnInsert(True)
char = QTextCharFormat()
char.setObjectType(QTextFormat.UserObject + 1)
char.setProperty(1, image)
char.setProperty(2, image_info[1])
char.setProperty(3, image_info[2])
char.setProperty(4, image_info[3])
plot_image_dict[self.current_edit_imagenum] = [image, image_info[1], image_info[2], image_info[3]]
tc.insertText("\ufffc", char)
tc.setKeepPositionOnInsert(False)
def closeEvent(self, event):
self.updateImage()
return pg.GraphicsLayoutWidget.closeEvent(self, event)
class PlotTextEditor(QMainWindow):
def __init__(self):
super().__init__()
self.plotview = PlotView()
self.pyplotObjectInterface = PlotObjectInterface()
self.plotview.plot_tedit.document().documentLayout().registerHandler(QTextFormat.UserObject+1,self.pyplotObjectInterface)
self.plotview.plot_tedit.viewport().installEventFilter(self)
self.setCentralWidget(self.plotview)
toolbar = QToolBar()
plotAction = QAction('Plot', self)
plotAction.triggered.connect(self.insertImage)
toolbar.addAction(plotAction)
self.addToolBar(toolbar)
self.setGeometry(300, 100, 800, 1000)
self.test_glWidget = PlotGraphicsLayoutWidget()
self.test_glWidget.current_text_edit = self.plotview.plot_tedit
self.test_manipulation = False
x = np.linspace(0, 10, 100)
y = np.sin(x)
plot = self.test_glWidget.addPlot()
#PlotDataItem
plot.plot(x, y, pen = 'b')
def closeEvent(self, event):
QApplication.closeAllWindows()
return QMainWindow.closeEvent(self, event)
def eventFilter(self, obj, event):
if event.type() == QMouseEvent.MouseButtonPress and obj == self.plotview.plot_tedit.viewport():
tc = self.plotview.plot_tedit.textCursor()
position = tc.position()
tc.movePosition(tc.Left, tc.KeepAnchor,1)
if tc.selectedText() == "\ufffc":
self.editImage(tc)
tc.clearSelection()
tc.setPosition(position)
p_next = position + 1
tc.setPosition(p_next, tc.KeepAnchor)
if tc.selectedText() == "\ufffc":
print("next character is \ufffc")
tc.clearSelection()
self.editImage(tc)
return False
return QMainWindow.eventFilter(self, obj, event)
def editImage(self, tc):
tc = QTextCursor(tc)
rect = self.plotview.plot_tedit.cursorRect(tc)
topLeft = rect.topLeft()
child_topLeft = self.plotview.mapToGlobal(topLeft)
char = tc.charFormat()
plot_img = char.property(1)
plot_num = char.property(2)
filename = char.property(3)
char.setProperty(4, tc.position())
if plot_img is not None:
geometry = QRect(topLeft,QSize(plot_img .width(), plot_img .height()))
self.test_glWidget.current_edit_filename = filename
self.test_glWidget.current_edit_imagenum = plot_num
self.test_glWidget.current_edit_image = plot_img
self.test_glWidget.current_edit_position = tc.position()
plot_image_dict[self.test_glWidget.current_edit_imagenum] = [plot_img, plot_num, filename, tc.position()]
self.test_glWidget.setGeometry(geometry)
self.test_glWidget.show()
def insertImage(self):
pg.QtGui.QApplication.processEvents()
exporter = pg.exporters.ImageExporter(self.test_glWidget.scene())
filename = os.path.join(os.getcwd(), "plot.png")
exporter.export(filename)
plot_img = QImage()
plot_img.load(filename)
plot_num = len(plot_image_dict)
plot_char = QTextCharFormat()
plot_char.setObjectType(QTextFormat.UserObject+1)
plot_char.setProperty(1, plot_img)
plot_char.setProperty(2, plot_num)
plot_char.setProperty(3, filename)
plot_char.setProperty(4, 0)
self.plotview.plot_tedit.textCursor().insertText("\ufffc", plot_char)
plot_image_dict[plot_num] = [plot_img, plot_num, filename, 0]
if __name__ == "__main__":
app = QApplication(sys.argv)
pte = PlotTextEditor()
pte.show()
sys.exit(app.exec_())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.