Как покрасить ячейки после создания Qtableview, используя пользовательский QAbstractTableModel - PullRequest
2 голосов
/ 20 марта 2020

Я создаю класс 'pandasModel' на основе QAbstractTableModel, как показано ниже:

import sys
from PyQt5.QtGui     import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore    import *
class pandasModel(QAbstractItemModel):

    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.index.size

    def columnCount(self, parent=None):
        return self._data.columns.size

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.EditRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, rowcol, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[rowcol]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[rowcol]
        return None

    def flags(self, index):
        flags = super(self.__class__, self).flags(index)
        flags |= Qt.ItemIsEditable
        flags |= Qt.ItemIsSelectable
        flags |= Qt.ItemIsEnabled
        flags |= Qt.ItemIsDragEnabled
        flags |= Qt.ItemIsDropEnabled
        return flags

    def sort(self, Ncol, order):
        """Sort table by given column number.
        """
        try:
            self.layoutAboutToBeChanged.emit()
            self._data = self._data.sort_values(self._data.columns[Ncol], ascending=not order)
            self.layoutChanged.emit()
        except Exception as e:
            print(e)

Также я создаю QTableView для отображения модели, показанной ниже:

class TableWin(QWidget):
    pos_updown = -1
    pos_save = []

    def __init__(self):
        super(TableWin, self).__init__()
        self.resize(200, 100)
        self.table = QTableView(self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.table)
        self.setLayout(self.v_layout)
        self.showdata()

    def showdata(self):
        data = pd.DataFrame([[1,2,3,4],[5,6,7,8]])
        model = pandasModel(data)
        self.table.setModel(model)

    def set_cell_color(self, row, column)
        '''
          Pass two arguments to this function, which is called to set
          the background color of the cell corresponding to the row and column
        '''
if __name__ == '__main__':
    app = QApplication(sys.argv)
    tableView = TableWin()
    # I want to change cell's color by call function 'set_cell_color' here
    # tableView.set_cell_color(row=1,column=1) 
    tableView.show()
    sys.exit(app.exec_())

Мы можем показать данные в QTableview сейчас, но вопрос в том, как я могу вызвать функцию 'set_cell_color', чтобы установить цвет фона для ячейки с заданными строкой и столбцом, поэтому не могли бы вы сказать мне, как завершить sh код в def set_cell_color?

как только я хочу установить цвет ячейки с помощью 'model.item (row, col) .setBackground (QColor (240, 255, 240)) ", так же как QStandardItemModel, но выдает ошибку" модель "не имеет атрибута" item ''

эта ссылка показывает метод для установки цвета ячейки

код показан ниже:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class Model(QAbstractTableModel):
    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        self._data = [[['%d - %d' % (i, j), False] for j in range(10)] for i in range(10)]

    def rowCount(self, parent):
        return len(self._data)

    def columnCount(self, parent):
        return len(self._data[0])

    def flags(self, index):
        return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable

    def data(self, index, role):
        if index.isValid():
            data, changed = self._data[index.row()][index.column()]

        if role in [Qt.DisplayRole, Qt.EditRole]:
            return data

        if role == Qt.BackgroundRole and data == "In error":        # <---------
            return QBrush(Qt.red) 

    def setData(self, index, value, role):
        if role == Qt.EditRole:
            self._data[index.row()][index.column()] = [value, True]
            self.dataChanged.emit(index, index)
            return True
        return False

if __name__ == '__main__':
    app = QApplication(sys.argv)
    tableView = QTableView()
    m = Model(tableView)
    tableView.setModel(m)
    tableView.show()
    sys.exit(app.exec_())

Use 'return QBru sh (Qt.red) Функция «in» data on может устанавливать цвет фона ячеек со значением «In error», но цвет фона уже был установлен при создании Qtableview fini sh, я просто хочу установить ячейку цвет фона при вызове функции 'set_cell_color ', это означает, что я могу контролировать фон ячейки даже после того, как Qtableview уже создан, я буду очень признателен за вашу помощь.

1 Ответ

1 голос
/ 20 марта 2020

Лог c предназначен для сохранения информации в модели, связывающей позицию элемента и цвет элемента, и для ее обновления должен быть подан сигнал dataChanged.

Примечание. Ваша модель имеет тип таблицы, поэтому вы должны наследовать от QAbstractTableModel, а не от QAbstractItemModel

Учитывая вышеизложенное, решение:

class pandasModel(QAbstractTableModel):
    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data

        self.colors = dict()

    def rowCount(self, parent=None):
        return self._data.index.size

    def columnCount(self, parent=None):
        return self._data.columns.size

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.EditRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.BackgroundRole:
                color = self.colors.get((index.row(), index.column()))
                if color is not None:
                    return color
        return None

    def headerData(self, rowcol, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[rowcol]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[rowcol]
        return None

    def flags(self, index):
        flags = super(self.__class__, self).flags(index)
        flags |= Qt.ItemIsEditable
        flags |= Qt.ItemIsSelectable
        flags |= Qt.ItemIsEnabled
        flags |= Qt.ItemIsDragEnabled
        flags |= Qt.ItemIsDropEnabled
        return flags

    def sort(self, Ncol, order):
        """Sort table by given column number.
        """
        try:
            self.layoutAboutToBeChanged.emit()
            self._data = self._data.sort_values(
                self._data.columns[Ncol], ascending=not order
            )
            self.layoutChanged.emit()
        except Exception as e:
            print(e)

    def change_color(self, row, column, color):
        ix = self.index(row, column)
        self.colors[(row, column)] = color
        self.dataChanged.emit(ix, ix, (Qt.BackgroundRole,))


class TableWin(QWidget):
    pos_updown = -1
    pos_save = []

    def __init__(self):
        super(TableWin, self).__init__()
        self.resize(200, 100)
        self.table = QTableView(self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.table)
        self.setLayout(self.v_layout)
        self.showdata()

    def showdata(self):
        data = pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8]])
        self.model = pandasModel(data)
        self.table.setModel(self.model)

    def set_cell_color(self, row, column):
        self.model.change_color(row, column, QBrush(Qt.red))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...