0

I'm a new in python.

Because I need create multiple figure (more than 300) in gui, add QWidget in QStackedWidget and connect to QListWidget,

I want to use QThread to save time, and found and answer at here.

This part is following the answer:

class MplFigure(object):
    def __init__(self,parent):
        self.figure=plt.figure()
        self.canvas=FigureCanvas(self.figure)

class plotThread(QThread):
    finished=pyqtSignal()
    def __init__(self,main_figure,ax1):
        super(plotThread, self).__init__()
        self.main_figure=main_figure
        self.ax1=ax1

    def run(self):
        x = randint(10000, size=300)
        y = randint(10000, size=300)
        self.ax1.scatter(x, y)
        
        self.main_figure.canvas.draw()
        self.finished.emit()

# stack widget part in GUI

    def stack_ui(self, n):
        # create fig from MplFigure and add ax1
        self.main_fig = MplFigure(self) 
        self.ax1 = self.main_fig.figure.add_subplot(111)
        
        # put fig to layout 
        self.sbox = QHBoxLayout()
        self.sbox.addWidget(self.main_fig.canvas) 
        
        # QThread part 
        self.worker = plotThread(self.main_fig, self.ax1)
        self.worker.start()

        # set layout to each stack 
        self.stack[n].setLayout(self.sbox)

The code is worked, and it will save time to create figure.

But in actually, it will get freeze gui, so I need more time to wait figure in layout.

here and here and here are the others answer that using moveToThread I found.

But those example code are too simple, just send a count number on the gui.

I think I need to put something as this part:

class Worker(QObject):

finished = pyqtSignal()

def do_the_work(self):
    # do the long task and even the plotting
    self.finished.emit()

But I have no idea what part should I put in there.

Could you guys show me more detail code with my case?

I will very appriciate your answer.

Here is the full code I writing now, it's will freeze gui.

from PyQt5.QtWidgets import * 
from numpy.random import randint 
import sys 
from PyQt5.QtCore import QThread, pyqtSignal
import matplotlib.pyplot as plt 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from datetime import datetime 

start = datetime.now()

def random():
    return randint(10000, size=1000)

class MplFigure(object):
    def __init__(self,parent):
        self.figure=plt.figure()
        self.canvas=FigureCanvas(self.figure)

class plotThread(QThread):
    finished=pyqtSignal()
    def __init__(self,main_figure,ax1):
        super(plotThread, self).__init__()
        self.main_figure=main_figure
        self.ax1=ax1

    def run(self):
        x = randint(10000, size=300)
        y = randint(10000, size=300)
        self.ax1.scatter(x, y)
        
        self.main_figure.canvas.draw()
        self.finished.emit()

# Create Window 
class Window(QWidget):
    def __init__(self):
        super().__init__()

        # get left list name from random
        self.leftlist_name = random()

        # Create tabs 
        tabs = QTabWidget()
        tabs.addTab(self.tab1_func(), 'Tab1')
        tabs.addTab(self.tab2_func(), 'Tab2')

        # Create a button to refresh Tab1 
        refresh_btn = QPushButton('Refresh Interface')
        refresh_btn.clicked.connect(self.refresh_func)

        # vboxlayout 
        self.vbox = QVBoxLayout()
        self.vbox.addWidget(refresh_btn)
        self.vbox.addWidget(tabs)
        
        # set layout 
        self.setLayout(self.vbox)

    # seet tab1 function 
    def tab1_func(self):
        tab1 = QWidget()
        self.hbox = QHBoxLayout() # if refresh delete widget in this layout 
        
        leftlist = QListWidget()
        leftlist.setFixedWidth(150)
        Stack = QStackedWidget()
        # create widget in Stack with each leftlist name 
        self.stack = {} 
        for n in range(len(self.leftlist_name)):
            leftlist.insertItem(n, str(self.leftlist_name[n]))
            self.stack[n] = QWidget()
            Stack.addWidget(self.stack[n])

        # connect leftlist and Stack 
        leftlist.currentRowChanged.connect(Stack.setCurrentIndex)

        # add widget in layout 
        self.hbox.addWidget(leftlist)
        self.hbox.addWidget(Stack)
        
        # set tab1 layout 
        tab1.setLayout(self.hbox)

        # go to set each leftlist name widget 
        for n in range(len(self.leftlist_name)):
            self.stack_ui(n)
        
        return tab1
    
    # set each leftlist name ui 
    def stack_ui(self, n):
        # create fig from MplFigure and add ax1
        self.main_fig = MplFigure(self) 
        self.ax1 = self.main_fig.figure.add_subplot(111)
        
        # put fig to layout 
        self.sbox = QHBoxLayout()
        self.sbox.addWidget(self.main_fig.canvas) 
        
        # QThread part 
        self.worker = plotThread(self.main_fig, self.ax1)
        self.worker.start()

        # set layout to each stack 
        self.stack[n].setLayout(self.sbox)

    def tab2_func(self):
        tab2 = QWidget()
        return tab2 
    
    def refresh_func(self):
        self.start = datetime.now()
        self.vbox.takeAt(1).widget().deleteLater()
        tabs = QTabWidget()
        tabs.addTab(self.tab1_func(), 'Tab1')
        tabs.addTab(self.tab2_func(), 'Tab2')

        self.vbox.addWidget(tabs)

        self.end = datetime.now()
        print(f"Refresh used time: {self.end-self.start}")
        return 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Window()
    w.showMaximized()

    end = datetime.now()
    print(f"Time used: {end-start}")


    sys.exit(app.exec_())
Ryan
  • 25
  • 3

0 Answers0