0
import sys
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QApplication, QItemDelegate, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt6.QtCore import Qt
import pandas as pd


class ComboBoxDelegate(QItemDelegate):
    def __init__(self, parent=None):
        super(ComboBoxDelegate, self).__init__(parent)
        self.items = []

    def setItems(self, items):
        self.items = items

    def createEditor(self, widget, option, index):
        editor = QtWidgets.QComboBox(widget)
        editor.addItems(self.items)
        return editor

    def setEditorData(self, editor, index):
        value = index.model().data(index, Qt.ItemDataRole.EditRole)
        if value:
            editor.setCurrentText(str(value))
            print("Data Changed")

    def setModelData(self, editor, model, index):
        model.setData(index, editor.currentIndex(), Qt.ItemDataRole.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.window_width, self.window_height = 700, 500
        self.resize(self.window_width, self.window_height)
        self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')

        layout = QVBoxLayout()
        self.setLayout(layout)

        self.table = QTableWidget()
        layout.addWidget(self.table)

        self.button = QPushButton('&Load Data')
        self.button.clicked.connect(lambda _, xl_path=excel_file_path,: self.loadExcelData(xl_path))
        layout.addWidget(self.button)

    def loadExcelData(self, excel_file_dir):
        df = pd.read_csv(excel_file_dir)
        if df.size == 0:
            return

        df.fillna('', inplace=True)
        self.table.setRowCount(df.shape[0])
        self.table.setColumnCount(df.shape[1])
        self.table.setHorizontalHeaderLabels(df.columns)

        # returns pandas array object
        for row in df.iterrows():
            values = row[1]
            for col_index, value in enumerate(values):
                if isinstance(value, (float, int)):
                    value = '{0:0,.0f}'.format(value)
                tableItem = QTableWidgetItem(str(value))
                self.table.setItem(row[0], col_index, tableItem)
        self.create_delegate(self.table)
        self.table.setColumnWidth(2, 300)
    
    def create_delegate(self, table):
        test_del = ComboBoxDelegate()
        test_list = ["Gravity Main", "Manhole", "Lateral"]
        test_del.setItems(test_list)
        table.setItemDelegateForColumn(0, test_del)


if __name__ == '__main__':
    
    excel_file_path = "[Your CSV]"

    app = QApplication(sys.argv)
    app.setStyleSheet('''
        QWidget {
            font-size: 17px;
        }
    ''')
    
    myApp = MyApp()
    myApp.show()

    try:
        sys.exit(app.exec())
    except SystemExit:
        print('Closing Window...')

Extension to previous question
Change the file directory to a random csv.
This populates the QTableWidget and does the same thing as my main program.
The QTableWidget does not save the changes.
My goal is to be able to populate multiple columns with different options based on the csv that is loaded. I had a working version but using QTableView instead of QTableWidget and I am working on transferring that progress.

Francom66
  • 1
  • 2
  • Changing the index of the combo alone won't change the model data, it would *probably* change if the editor is *not* persistent, so you should connect the `currentIndexChanged` signal of the combo to a function that properly calls `setModelData()`. I'd suggest you to provide a proper [mre] so that we could answer you more precisely. – musicamante Jan 06 '22 at 14:24
  • I have a reproducible example ready but SO does not let me post for another hour. https://github.com/FrancoM66/Reproducible-Example I added it to this repo with an example csv – Francom66 Jan 06 '22 at 15:10
  • You don't have to create a new post, [edit] this question instead. – musicamante Jan 06 '22 at 15:27
  • Question edited Thank you for the responses btw – Francom66 Jan 06 '22 at 15:57
  • I can confirm the issue, and it was recently reported in the PyQt mailing list too (see https://www.riverbankcomputing.com/pipermail/pyqt/2022-January/044444.html ) even though the maintainer cannot confirm it. (note: for future reference, try to do some more efforts to produce a MRE: for instance, there's absolutely no need for a button to load a model and use a csv, as a basic structure with arbitrary values created in a for loop would have sufficed, and it would have made your code much simpler, shorter and easier to read, without any unnecessary part). – musicamante Jan 06 '22 at 19:38

1 Answers1

0

The issue is caused by a code generation bug, according to the PyQt maintainer.

It should have been fixed in the following PyQt6 snapshots, so it's very likely that if you do a pip update you'll get the working version already, otherwise wait a couple of days and keep an eye on the changelog of the official site.

musicamante
  • 41,230
  • 6
  • 33
  • 58