PySide 6: GUI Freezing even when using QThreadPool class
-
I am currently building a GUI using PySide6. I am running into some issues with the qthreadpool threading.
I have a method where I perform some heavy computation, that will end up freezing the GUI if left on the main thread. I have used qthreadpool for otber methods in my code, and it has worked just fine. For some reason, there is a specific part of my code right now that isn't working as intended. I launch that method in a threadpool thread, and the GUI still freezes up. To me this means that it's not making it outside the mainthread, or there is some other bigger issue. I can't really narrow it down, since I've been using qthreadpool this whole time and it has worked fine.
ANy guidance or help with this would be great, I am a bit stuck at this point.
Here is my code:
class dataSignal(QObject): data_received = Signal(object) class DataPlotting(QMainWindow): def __init__(self): super(DataPlotting, self).__init__() # Styling and window layout screen = QApplication.primaryScreen().size().width() window = self.frameGeometry().width() self.move(int(screen / 2) - int(window / 2),0) self.setWindowTitle('GUI App') self.setStyleSheet('''...''') # Initializing Variables for data log file self.threadpool = QThreadPool() self.plotting_signal_con = dataSignal() self.plotting_signal_con.data_received.connect(self.plotting_ready) self.data = {} # Sample Button to Graph Data, this is the button where I launch heavy computation # but the GUI still freezes self.graph = QPushButton('Graph Data', self) self.graph.setToolTip('Graph Data') self.graph.setEnabled(False) self.graph.clicked.connect(self.threader) # connects to funciton that launches thread @Slot() def plotting_ready(self, info): # Here all i do is call a function in another file that plots the data based on selected x and y # variables (not included in this code) self.console.append(info) plotting(list(self.data.values()), self.xvar, self.yvars, self.footers) def plot_cb(self, info): self.plotting_signal_con.data_received.emit(info) # We launch the thread here def threader(self): self.threadpool.start(self.ProcessDataLogs2(self.plot_cb)) def ProcessDataLogs2(self, callback): for i, file in enumerate(self.data): #This is where the heavy computation happens # All i really do is read in a file from pandas based on different conditions, so I am just going to # include that line df = pd.read_csv(file self.data[file]) = df # Once that is done, we send info in the call back function to signal that this process is done, and it goes to the function plotting_ready info = 'Data Processing Finished & Plots Created...' callback(info)
-
Hi,
I think the issue is that you are using a callback to emit the signal.
If you want to emit a signal from a different thread, you should use QMetaObject::invokeMethod.
-
@SGaist Hi I appreciate your response.
I dont think that this is the problem if I am being honest. The reason why I say that is because I am doing the exact same process for another method in my code, and that one works exactly as intended.
If it helps, here is the code for that chunk:
class dataSignal(QObject): data_received = Signal(object) class DataPlotting(QMainWindow): def __init__(self): super(DataPlotting, self).__init__() # Styling and window layout screen = QApplication.primaryScreen().size().width() window = self.frameGeometry().width() self.move(int(screen / 2) - int(window / 2),0) self.setWindowTitle('GUI App') self.setStyleSheet('''...''') # Initializing Variables for data log file self.threadpool = QThreadPool() self.signal_con = dataSignal() self.signal_con.data_received.connect(self.data_ready) self.data = {} self.pandas_profile_button = QPushButton('Build Statistical Report') self.pandas_profile_button.setToolTip('Creates an HTML file containing a statistical breakdown of selected data') self.pandas_profile_button.setEnabled(False) self.pandas_profile_button.clicked.connect(self.pandas_report_th) @Slot() def data_ready(self, info): self.progress_bar.setValue(100) self.console.append(info) def cb(self, info): self.signal_con.data_received.emit(info) def pandas_report_th(self): self.threadpool.start(self.pandas_report) def pandas_report(self): # This one essentially odes the same thing, read a csv and process it for some actions, it goes one thread farther df = pd.read_csv(file self.data[file]) = df self.threadpool.start(self.pandas_report5(self.cb)) def pandas_report5(self, callback): prof = ProfileReport(self.data[file]) filename = file.replace('.txt', ' Statistical Report.html') prof.to_file(output_file=filename) print('Report done') result = 'Your report has been saved at: ' + filename callback(result)
-
So the one that creates a file is working but the one that changes a GUI element freezes ? Do I get you correctly ?