0

when I try to load some .pdf which size>10MB or pages>300 ,

the worker thread will block the main thread , I don't know how to use QThread correctly,

I want by each time the pixmap_page_load run , the signal is emitted to the main thread.

here is the minimum code , need module pymupdf and a pdf file

import time

from PyQt5.QtCore import QRectF, Qt, pyqtSignal, QThread
from PyQt5.QtGui import QColor, QBrush, QPen, QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsLineItem, QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsItem, \
    QFileDialog

from fitz import fitz

def pixmap_page_load(doc:"fitz.Document", pagenum, ratio=1):

    page:"fitz.Page" = doc.load_page(pagenum)  # 加载的是页面
    pix:"fitz.Pixmap" = page.getPixmap(matrix=fitz.Matrix(ratio, ratio))  # 将页面渲染为图片
    fmt = QImage.Format_RGBA8888 if pix.alpha else QImage.Format_RGB888  # 渲染的格式

    pageImage = QImage(pix.samples, pix.width, pix.height, pix.stride, fmt)
    pixmap = QPixmap()
    pixmap.convertFromImage(pageImage)  # 转为pixmap
    return QPixmap(pixmap)

class MyGraphicRect2(QGraphicsItem):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.setPos(self.x, self.y)
        self.color = QColor('red')

        self.setAcceptDrops(True)
        self.setCursor(Qt.OpenHandCursor)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QGraphicsItem.ItemIsFocusable, True)
        self.setAcceptHoverEvents(True)

    def setColor(self, color):
        self.color = QColor(color)

    def boundingRect(self):
        return QRectF(self.x, self.y, self.width, self.height)

    def paint(self, painter, options, widget):
        painter.setPen(QPen(QColor('black')))
        painter.setBrush(self.color)
        painter.drawRect(self.x, self.y, self.width, self.height)


class MoveThread(QThread):
    s = pyqtSignal(float, float)
    def __init__(self,directory):
        super().__init__()
        self.directory=directory
    def run(self):

        doc= fitz.open(self.directory)
        for i in range(1,len(doc)):
            pixmap = pixmap_page_load(doc,i)
            self.s.emit(i,0)


class MyGraphicScene(QMainWindow):
    def __init__(self):
        super().__init__()
        self.rect=QRectF(0,0,800,800)
        self.Scene=QGraphicsScene(self.rect)
        self.View=QGraphicsView()
        self.View.setCacheMode(QGraphicsView.CacheNone)
        self.sceneConfig()
        self.displayUI()

    def sceneConfig(self):
        self.Scene.setBackgroundBrush(QBrush(QColor('yellow'),Qt.SolidPattern))

        self.item1=MyGraphicRect2(100,100,100,100)
        self.Scene.addItem(self.item1)
        line=QGraphicsLineItem(80,38,84,38)
        self.Scene.addItem(line)
        self.View.setScene(self.Scene)

    def updatePosition(self, x, y):
        item1 = MyGraphicRect2(100+x, 100+y, 100, 100)
        self.Scene.addItem(item1)

    def displayUI(self):
        print('Is scene active', self.Scene.isActive())
        directory, _ = QFileDialog.getOpenFileName(None, "选取文件", ".", "(*.pdf)")
        self.setCentralWidget(self.View)
        self.th=MoveThread(directory)
        self.th.s.connect(self.updatePosition)
        self.th.start()
        self.resize(1000,1000)
        self.show()

if __name__ == "__main__":
    import sys
    app=QApplication(sys.argv)

    m=MyGraphicScene()

    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
nevermind_15
  • 217
  • 1
  • 6
  • 1
    I cannot test your code, but it's not safe to create a QPixmap outside the UI thread. Use the QImage in the thread and convert it to QPixmap whenever necessary *only* in the UI thread. Also, please use more descriptive names, don't use uppercase variables and attributes, add spaces around the equal sign, and don't overwrite existing class members (such as `self.rect`). While these seems very trivial aspects, they are *not*, as making your code more readable is very important (and also helps us in focusing on your problem, instead of being distracted by your syntax). – musicamante Jun 15 '21 at 13:03
  • Does this answer your question? [Background thread with QThread in PyQt](https://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt) – Lenormju Jun 16 '21 at 07:15

0 Answers0