2
\$\begingroup\$

I'm doing a larger PyQt5 project which includes loading in large amount of data into a QTableWidget. However filling the table up with the loaded data is extremely slow due to nested for loops. I put there a minimal working example. The loaded .txt files usually look like this:

...
3.137856026645493124e+00,-1.018072816226149244e-02
3.137333399059442751e+00,2.133285461296379468e-04
3.136810945537534145e+00,6.040261342268495991e-04
3.136288665992822633e+00,6.455403916425843380e-03
3.135766560338420383e+00,3.788118428284327315e-03
3.135244628487498630e+00,3.439159817145511638e-02
3.134722870353285007e+00,-8.456704230609860635e-04
3.134201285849066654e+00,2.062391644217435177e-02
3.133679874888186667e+00,-1.154215762495692556e-02
3.133158637384046763e+00,-3.520437354375163114e-02
3.132637573250105945e+00,4.354430655996290934e-05
...

main.py

from PyQt5.QtWidgets import QFileDialog
from PyQt5 import QtWidgets, QtCore

import numpy as np

from ui import Ui_MainWindow

class MainProgram(QtWidgets.QMainWindow, Ui_MainWindow):
    x_val = np.array([])
    y_val = np.array([])

    def __init__(self, parent = None):
        super(MainProgram, self).__init__(parent)
        self.setupUi(self)
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(5)
        self.tableWidget.setHorizontalHeaderLabels(["Angular frequency", "Intensity"])
        self.tableWidget.setSizeAdjustPolicy(
        QtWidgets.QAbstractScrollArea.AdjustToContents)

        self.btn_load.clicked.connect(self.load_data)

    def load_data(self): 
            options = QFileDialog.Options()
            fileName, _ = QFileDialog.getOpenFileName(None,"Title..", "",
                                                      "All Files (*);;Text Files (*.txt)", options=options)
            try:
                if fileName:
                    self.tableWidget.setRowCount(0) 
                    self.x_val, self.y_val = np.loadtxt(fileName, usecols=(0,1), unpack = True, delimiter =',')   
                    """ as you can see I limit the max lines, but even at max 800
                         it's slow"""
                    if len(self.x_val)<800:
                        for row_number in range(len(self.x_val)):
                            self.tableWidget.insertRow(row_number)
                            for item in range(len(self.x_val)):
                                self.tableWidget.setItem(item, 0, QtWidgets.QTableWidgetItem(str(self.x_val[item])))
                            for item in range(len(self.y_val)):
                                self.tableWidget.setItem(item, 1, QtWidgets.QTableWidgetItem(str(self.y_val[item])))
                    else:
                        for row_number in range(800):
                            self.tableWidget.insertRow(row_number)
                            for item in range(800):
                                self.tableWidget.setItem(item, 0, QtWidgets.QTableWidgetItem(str(self.x_val[item])))
                            for item in range(800):
                                self.tableWidget.setItem(item, 1, QtWidgets.QTableWidgetItem(str(self.y_val[item])))
                self.tableWidget.resizeRowsToContents()
                self.tableWidget.resizeColumnsToContents()
            except Exception as e:
                print(e)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    my_interface = MainProgram()
    my_interface.show()
    sys.exit(app.exec_())

ui.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ui.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.btn_load = QtWidgets.QPushButton(self.centralwidget)
        self.btn_load.setObjectName("btn_load")
        self.verticalLayout.addWidget(self.btn_load)
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.verticalLayout.addWidget(self.tableWidget)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.btn_load.setText(_translate("MainWindow", "Load"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

My question is: Can this be optimized in any way? Thank you for answering.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Sorry, but I thought you overdid it with loops in the load_data method.

Try your example with the load_data method, which looks like this:

# ...

def load_data(self): 
    options = QFileDialog.Options()
    fileName, _ = QFileDialog.getOpenFileName(None,"Title..", "",
                                              "Text Files (*.txt)", options=options)
    if fileName:
        self.tableWidget.setRowCount(0) 
        self.x_val, self.y_val = np.loadtxt(fileName, usecols=(0,1), unpack = True, delimiter =',')   
        for row in range(len(self.x_val)):
            self.tableWidget.insertRow(row)
            self.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(str(self.x_val[row])))
            self.tableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem(str(self.y_val[row])))
    self.tableWidget.resizeColumnsToContents()

# ...
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.