Модель / Вид PyQt5 - одна модель, два вида - PullRequest
2 голосов
/ 27 апреля 2020

Я разрабатываю приложение, используя PyQt5. Мне нужно отображать одни и те же данные в двух таблицах, но по-разному для каждой таблицы. То есть: первая таблица редактируема. Можно редактировать несколько элементов (их имена, значения и т. Д. c.)

enter image description here

Вторая таблица, однако, должна отображать первый столбец первая таблица (имя элемента) в вертикальных заголовках и один из столбцов первой таблицы (в этом примере третьей) в качестве единственной строки:

(я этого не достиг, я нарисовал его для лучшее понимание)

enter image description here

Чтобы данные были согласованными между двумя таблицами (и внутри, поскольку значения в таблицах используются для других операций) Я думаю, что использование модели / архитектуры - лучший способ go. Я начал реализовывать модель (наследующую QAbstractTableModel) для первой таблицы, но методы в этом классе модели (data, rowCount, columnCount, ...) должны сильно отличаться для каждой таблицы.

Как я должен подойти к этой проблеме? Должен ли я создать собственный класс View для второй таблицы?

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Если вы хотите получить новую модель на основе другой модели, вы можете использовать QXProxyModel. В вашем конкретном случае вы можете преобразовать модель, используя следующую процедуру:

  • Повернуть таблицу с помощью QTransposeProxyModel.
  • Скрыть строки с помощью hideRow ().
  • Сопоставьте заголовок, внедрив прокси на основе QIdentityProxyModel.
from PyQt5 import QtCore, QtGui, QtWidgets


class CustomProxyModel(QtCore.QIdentityProxyModel):
    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.sourceModel().index(0, section).data(role)
            else:
                return 1
        return super().headerData(section, orientation, role)

    def setSourceModel(self, model):
        super().setSourceModel(model)
        model.dataChanged.connect(self._on_headerDataChanged)

    def _on_headerDataChanged(self, topLeft, bottomRight, roles):
        if topLeft.row() <= 0 <= bottomRight.row():
            self.headerDataChanged.emit(
                QtCore.Qt.Horizontal, topLeft.row(), bottomRight.row()
            )


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    model = QtGui.QStandardItemModel(3, 4)

    datas = (
        ("Element 1", "2", "3", "4"),
        ("Another element", "6", "7", "8"),
        ("Element nr. 3", "10", "11", "12"),
    )

    for i, r in enumerate(datas):
        for j, d in enumerate(r):
            it = QtGui.QStandardItem(d)
            model.setItem(i, j, it)

    proxy = QtCore.QTransposeProxyModel()
    proxy.setSourceModel(model)

    proxy2 = CustomProxyModel()
    proxy2.setSourceModel(proxy)

    view1 = QtWidgets.QTableView()
    view1.setModel(model)

    view2 = QtWidgets.QTableView()
    view2.setModel(proxy2)

    for r in range(proxy.rowCount()):
        if r != 2:
            view2.hideRow(r)

    w = QtWidgets.QWidget()
    lay = QtWidgets.QHBoxLayout(w)
    lay.addWidget(view1)
    lay.addWidget(view2)
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

enter image description here

1 голос
/ 27 апреля 2020

Отсутствующая часть в вашем дизайне - реализация шаблона проектирования наблюдателя для полноценного потока модели представления модели. вы можете реализовать свой собственный наблюдаемый контейнер данных для привязки к нескольким представлениям как здесь , или вы можете использовать стороннюю библиотеку наблюдателя от pypi. Я предлагаю реализовать свой собственный наблюдаемый контейнер данных, чтобы лучше управлять будущими изменениями, такими как транспонирование табличного представления, как в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...