Python 将Pyqtgraph嵌入Pyqt文本编辑

Python 将Pyqtgraph嵌入Pyqt文本编辑,python,pyqt,pyqtgraph,qtextedit,Python,Pyqt,Pyqtgraph,Qtextedit,我想创建一个文本编辑器,您可以在其中拖放Pyqtgraphs并与它们实时交互。我很难理解TextEdit的行为以及小部件如何“嵌入”TextEdit本身。查看API后,似乎只有文本、html和图像可以添加到QTextEdit中 我可能在这里抓住了救命稻草,但我希望有一个无效的QTextEdit::insertWidget(QWidget*)或者类似的东西 这里要澄清的是一个不完整的示例代码: import sys import numpy as np from PyQt5.QtGui impo

我想创建一个文本编辑器,您可以在其中拖放Pyqtgraphs并与它们实时交互。我很难理解TextEdit的行为以及小部件如何“嵌入”TextEdit本身。查看API后,似乎只有文本、html和图像可以添加到QTextEdit中

我可能在这里抓住了救命稻草,但我希望有一个
无效的QTextEdit::insertWidget(QWidget*)
或者类似的东西

这里要澄清的是一个不完整的示例代码:

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_())
我的一些想法是将pyqtgraph覆盖在空白图像上,或者尝试找到某种文本小部件,我可以插入并覆盖paintevent,为其提供pyqtgraph绘制。但最终,我不确定使用当前的带有TextEdit的Qt后端是否可以实现这一点。

请尝试此代码

如果你想了解更多信息,请发表评论。 我不知道你是否喜欢这个结果

更新转换

  • 可以渲染打印图像,但不渲染数据。 我将
    pen='r':plot.plot(x,y,pen)
    更改为
    plot.plot(x,y,pen='r')

  • 打印图像的数据是脏的,没有抗锯齿,被截取和关闭。 我更新
    intrinsicSize()
    并返回图像宽度和图像高度, 如果您在
    intrinsicSize
    中随意设置
    return QSizeF()
    参数,则可能会出现不好的结果

  • 尽可能以交互方式。 如您所见,此图像由
    QPainter
    绘制。因此,最初,这是不实用的。我认为这是将结果呈现为
    QTextObject
    的唯一方法
    QTextEdit
    无法接受一种小部件作为文本

  • 请点击图片前面。
    GraphicsLayoutWidget
    显示。您可以更改图形内容,然后关闭它。下一次,图像将重新绘制并再次渲染

  • 我删除了不必要的代码

  • 不管怎样,我一直在努力,直到现在

    请通过评论询问我更多信息

    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_())
    

    嘿,我很感激写这篇文章的努力,但是实际的绘图数据没有显示出来。这是故意的吗?@Michael Choi发生这种情况是因为我在
    绘图中写了
    pen='r'
    。绘图(x,y,pen)
    。我没有想到原因,所以我坚持了一会儿。对不起,我更新了,请查看我的答案。@user9402680谢谢。我需要一些时间来消化所有的代码,但它有我想要的功能。如果你有一个难以理解的地方,请不要犹豫,通过评论或新问题来问我。不过,如果可能的话,这可能是一个新问题。