Как получить текст из QLineEdit для обновления ячеек в QTableView - PullRequest
0 голосов
/ 25 января 2020

Обзор: у меня есть интерфейс, который отображает QTableView. Когда пользователь нажимает на строку в таблице, данные из этой строки заполняют несколько полей ввода QLineEdit, соответствующих информации в этой ячейке - например, столбец «АДРЕС» будет иметь соответствующий «АДРЕС» QLineEdit поле, в котором будут заполнены данные этого адреса.

Существующая функциональность: щелкнув строку, пользователь может щелкнуть QLineEdit и изменить текст в списке - например, если указан неправильный адрес, пользователь может нажать «АДРЕС» * 1007. * поле и измените его на что-то другое.

Желаемая функциональность: я хотел бы иметь возможность нажать кнопку «СОХРАНИТЬ» и получить данные в QLineEdit, а затем отразить в QTableView.

Проблема: Функция, которая запускается при нажатии кнопки «СОХРАНИТЬ», пытается обновить QTableView фрейм данных и обновить sh представление, но, по-видимому, изменения не вносятся, а данные QTableView сам по себе не отражает никаких изменений.

Примеры кода:

** примечание - когда пользователь нажимает на QTableView, запускается функция, которая инициализирует переменную self.user_selection, которая QModelIndex объект и ссылка ниже. Поля QLineEdit содержатся в QGridLayout, поэтому используется функция itemAtPosition ниже. self.comp_list - это заполняемый объект QTableView

Когда пользователь нажимает «SAVE», запускается следующая функция ...

def update_selected_comp_entry(self):
    # This will get all of the values for each column, for the row selected - this returns a 
    # QWidgetItem, which is why widget().text() must be used to retrieve the cell's data
    items = [self.comp_details_layout.itemAtPosition(i, 1) for i in range(self.comp_details_layout.count()) if isinstance(comp_details_layout.itemAtPosition(i, 1), PyQt5.QtWidgets.QWidgetItem)]

    for i, each in enumerate(items):
        self.comp_list.model().setData(self.user_selection, each.widget().text())

Упрощенная версия моего класса, которая заполняет QTableView:

class DataFrameModel(PyQt5.QtCore.QAbstractTableModel):
    def __init__(self, df=pandas.DataFrame(), parent=None):
        super(DataFrameModel, self).__init__(parent)
        self._dataframe = df.replace(numpy.nan, '', regex=True)

    def setDataFrame(self, dataframe):
        self.beginResetModel()
        self._dataframe = dataframe.copy()
        self.endResetModel()

    # @PyQt5.QtCore.pyqtSlot() - I've tried using this decorator and it didn't do anything
    # This function is my attempt at grabbing the user's input and updating 
    # the QTableView displayed data
    def setData(self, index, value, role=PyQt5.QtCore.Qt.EditRole):
        if index.isValid():
            row = index.row()
            col = index.column()

            # I've tried with and without the line below
            self.layoutAboutToBeChanged.emit()
            # I've tried using set_value() as well as iloc and neither worked
            self._dataframe.loc[row, col] = value
            # I';ve tried with and without this line, neither worked
            self.setDataFrame(self._dataframe)
            # I've also tried the dataChanged signal and that didn't work either
            self.layoutChanged.emit()
            return True
        return False

1 Ответ

0 голосов
/ 25 января 2020

Даже не беспокойтесь о функции setData, в ней нет необходимости, исходя из того, что у вас там есть. Поскольку вы уже получаете все данные из ячеек в переменной items, просто используйте ее, чтобы обновить источник, из которого вы вначале заполнили QTableView. Поскольку вы знаете, что этот метод работает, он будет принимать ваши обновленные данные, и вы можете обновить sh вашу таблицу, как обычно.

Для примера давайте предположим, что ваши заголовки столбцов такие же, как то, что у вас было для вашего widget (). objectName () будет для каждого вашего QWidgetItem в вашей переменной items. Очевидно, вы можете изменить это на любое, что захотите.

Вы можете создать словарь с именами столбцов в качестве ключей, а затем текст QLineEdit в качестве значения.

new_input = {metric.widget().objectName: metric.widget().text() for metric in items}

Затем просто отправьте эти данные обратно на ваш фрейм данных.

for key, value in zip(new_input.keys(), new_input.values()):
    # You said the self.user_selection was a QModelIndex, so you can get your selected
    # row from there
    df.loc[self.user_selection.row(), key] = value

Затем просто отправьте этот фрейм данных вашему классу, как обычно, чтобы заполнить эту таблицу.

...