将Pyqtgraph嵌入Pyqt Textedit

时间:2019-04-29 19:47:37

标签: python pyqt pyqtgraph qtextedit

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

我可能在这里抓住稻草,但我希望有void 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后端中是否还可以实现。

1 个答案:

答案 0 :(得分:2)

请尝试使用此代码。

如果您想了解更多信息,请通过评论询问我。 我不知道你是否喜欢这个结果。

更新过渡

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

  2. 绘图图像的数据很脏,并且没有抗锯齿,会断断续续地被拦截。 我更新intrinsicSize()并返回图片宽度和图片高度, 如果根据需要在return QSizeF()中设置intrinsicSize参数,则结果可能会很糟糕。

  3. 我们尽可能地互动。 如您所见,此图像由QPainter绘制。因此,本来这是非交互的。我认为这是将结果呈现为QTextObject的唯一方法。 QTextEdit不能接受一种小部件作为文本。

  4. 请单击图像前面。 显示GraphicsLayoutWidget。更改图形内容,然后将其关闭。下次,图像将重新绘制并再次渲染。

  5. 我删除了不必要的代码。

无论如何,我一直试图做到这一点。

请通过评论询问我进一步的消息。

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