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')
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.
Interactively as possible as we can.
As you can see, this image is drawn by QPainter. So , originally, this is uninteractive.I think this is the only way for rendering your result as QTextObject. QTextEdit can't accept a kind of widgets as text.
Please click in front of the image.
GraphicsLayoutWidget shows.and you change the graph contents, and you close it. 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_())