I’m working on a PyQt6 GUI that needs to call a function from a pyo3 library in the background, which performs very expensive calculations on a very large amount of data (we’re talking about vectors with a minimum length of one billion; the application is used in scientific contexts).
This function takes from a few seconds to several minutes to process the data sent to it. However, what I want to avoid is the GUI freezing and becoming unresponsive during the calculation.
So, I opted to use QThread, provided by PyQt6, and here’s an example of part of the implemented code:
class FCSPostProcessingWorker(QThread):
finished = pyqtSignal(object)
def __init__(self, active_correlations, num_acquisitions):
super().__init__()
self.active_correlations = active_correlations
self.num_acquisitions = num_acquisitions
self.is_running = True
def run(self):
gt_results = fcs_flim.fluorescence_correlation_spectroscopy(
num_acquisitions=self.num_acquisitions,
correlations=self.active_correlations,
)
self.finished.emit(gt_results)
def stop(self):
self.is_running = False
class FCSPostProcessing:
@staticmethod
def get_input(app):
correlations = [tuple(item) if isinstance(item, list) else item for item in app.ch_correlations]
active_correlations = [(ch1, ch2) for ch1, ch2, active in correlations if active]
#num_acquisitions = app.selected_average
num_acquisitions = 3
worker = FCSPostProcessingWorker(active_correlations, num_acquisitions)
QApplication.processEvents()
worker.finished.connect(lambda result: FCSPostProcessing.handle_fcs_post_processing_result(app, result, worker))
worker.start()
@staticmethod
def handle_fcs_post_processing_result(app, gt_results, worker):
worker.stop()
remove_widget(app.layouts[PLOT_GRIDS_CONTAINER], app.widgets[GT_WIDGET_WRAPPER])
gt_widget = create_gt_layout(app)
insert_widget(app.layouts[PLOT_GRIDS_CONTAINER], gt_widget, 1)
gt_plot_to_show = [tuple(item) if isinstance(item, list) else item for item in app.gt_plots_to_show]
lag_index = gt_results[0]
filtered_gt_results = [res for res in gt_results[1] if res[0] in gt_plot_to_show]
for index, res in enumerate(filtered_gt_results):
correlation = res[0]
gt_values = res[1]
FCSPostProcessingPlot.generate_chart(correlation, index, app, lag_index, gt_values)
The problem is that the GUI still freezes during the execution of the expensive function, and I haven’t noticed any changes since I introduced this new thread. Am I missing something? Thanks.