【问题标题】:How to add headers to qml TableView from TableModel如何从 TableModel 向 qml TableView 添加标题
【发布时间】:2019-08-01 20:19:42
【问题描述】:

我需要向使用 Python 中定义的自定义模型的 TableView 添加标题。

我尝试用我的自定义标题覆盖 QAbstractTableModel 中的 headerData 函数。我正在遵循相同类型实现的此 C++ 示例中描述的相同系列步骤:Header to a TableView

很遗憾,标题仍然没有显示在表格的顶部。然而,该表确实包含来自覆盖 QAbstractTableModel 中的数据函数的数据。

Python:

class RouteTableModel(QAbstractTableModel):

    def __init__(self, parent=None, *args): 
        super().__init__()
        self._datatable = None
        self._header = {
            0 : 'X',
            1 : 'Y',
            2 : 'Z'
        }

    def data(self, index, role=Value):
        i = index.row()
        j = index.column()
        if role == self.Value:
            return '{0}'.format(self._datatable[i][j]['value'])
        elif role == self.Selected:
            return self._datatable[i][j]['selected']
        else:
            return None

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return self._header[section]
            else:
                return None
        else:
            return None

# create the application instance
app = QApplication(sys.argv)

# create a QML engine
engine = QQmlApplicationEngine()

# instantiate the TableModel class
xyztablemodel = RouteTableModel()

engine.rootContext().setContextProperty('XYZTableModel', xyztablemodel)

# load main QML file and start app engine
engine.load('view.qml')

if not engine.rootObjects():
    sys.exit(-1)

sys.exit(app.exec_())

QML:

import QtQuick 2.12
import QtQuick.Controls 2.12
GridLayout {
    id: gridfpc2
    flow: GridLayout.TopToBottom
    rows: 4
    columns: 2
    rowSpacing: 20
    columnSpacing: 35

    TableView {
        id: xyztable
        Layout.rowSpan: 4
        // Layout.alignment: Qt.AlignCenter
        Layout.fillHeight: true

        model: XYZTableModel
        width: 350

        delegate: CustomComp.XYZTableDelegate {
            implicitWidth: parent.width / 3
            implicitHeight: 20
        }
    }
}

Python 或 qml 代码中不会出现错误消息。我希望标题填充在 TableView 中的列上方,但它们没有显示出来。

【问题讨论】:

  • 您使用的是什么 TableView:QQC1QQ
  • 我没有意识到有两种同名的类型。我假设它的 QQC1 因为我导入 QtQuick 和 QtQuick.Controls 第二。我如何确定我是否同时导入两者?
  • 原来是它的 QQ:stackoverflow.com/questions/57316457/… 我正在为 QtQuick 和 QtQuick.Controls 导入 2.12。该版本中仅存在 QtQuick 实现。

标签: python python-3.x qml tableview pyside2


【解决方案1】:

在您在问题中指出的示例中,它来自与 QML 提供的 TableView 非常不同的 QTableView。在您的情况下,您使用的是 QtQuick 的 TableView。此 TableView 没有标题,因此您必须实现它,在我的示例中,我将使用中继器。另一方面,无法从 QML 访问 headerData,因此我将使用 @Slot() 实现 C++ 的 Q_INVOKABLE,将返回函数的变量类型的结果作为参数传递:

ma​​in.py

from PySide2 import QtCore, QtGui, QtQml


class RouteTableModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._header = {0: "X", 1: "Y", 2: "Z"}

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 3

    def rowCount(self, parent=QtCore.QModelIndex()):
        return 100

    def data(self, index, role=QtCore.Qt.DisplayRole):
        i = index.row()
        j = index.column()
        if role == QtCore.Qt.DisplayRole:
            return "{}-{}".format(i, j)

    @QtCore.Slot(int, QtCore.Qt.Orientation, result="QVariant")
    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self._header[section]
            else:
                return str(section)


if __name__ == "__main__":
    import os
    import sys

    app = QtGui.QGuiApplication(sys.argv)

    engine = QtQml.QQmlApplicationEngine()

    xyztablemodel = RouteTableModel()
    engine.rootContext().setContextProperty("XYZTableModel", xyztablemodel)

    current_dir = os.path.dirname(os.path.realpath(__file__))
    filename = os.path.join(current_dir, "view.qml")

    engine.load(QtCore.QUrl.fromLocalFile(filename))

    if not engine.rootObjects():
        sys.exit(-1)

    sys.exit(app.exec_())

view.qml

import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Window 2.11

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    color: '#222222'

    TableView {
        id: tableView
        columnWidthProvider: function (column) { return 100; }
        rowHeightProvider: function (column) { return 60; }
        anchors.fill: parent
        leftMargin: rowsHeader.implicitWidth
        topMargin: columnsHeader.implicitHeight
        model: XYZTableModel
        width: 350
        delegate: Rectangle {
            implicitWidth: 100
            implicitHeight: 50
            Text {
                text: display
            }
        }

        Rectangle { // mask the headers
            z: 3
            color: "#222222"
            y: tableView.contentY
            x: tableView.contentX
            width: tableView.leftMargin
            height: tableView.topMargin
        }

        Row {
            id: columnsHeader
            y: tableView.contentY
            z: 2
            Repeater {
                model: tableView.columns > 0 ? tableView.columns : 1
                Label {
                    width: tableView.columnWidthProvider(modelData)
                    height: 35
                    text: XYZTableModel.headerData(modelData, Qt.Horizontal)
                    color: '#aaaaaa'
                    font.pixelSize: 15
                    padding: 10
                    verticalAlignment: Text.AlignVCenter

                    background: Rectangle { color: "#333333" }
                }
            }
        }
        Column {
            id: rowsHeader
            x: tableView.contentX
            z: 2
            Repeater {
                model: tableView.rows > 0 ? tableView.rows : 1
                Label {
                    width: 40
                    height: tableView.rowHeightProvider(modelData)
                    text: XYZTableModel.headerData(modelData, Qt.Vertical)
                    color: '#aaaaaa'
                    font.pixelSize: 15
                    padding: 10
                    verticalAlignment: Text.AlignVCenter
                    background: Rectangle { color: "#333333" }
                }
            }
        }

        ScrollIndicator.horizontal: ScrollIndicator { }
        ScrollIndicator.vertical: ScrollIndicator { }
    }
}

【讨论】:

  • 在已经实现标题的地方我可以使用另一个 TableView 吗?我能够使用您的解决方案来明确地实现它们,但是如果已经预先构建了一些东西,那么使用它可能是有意义的。看起来从 QtQuick.Controls 实现的 TableView 与我的模型实现不匹配,并且已在更新的版本中停用。
  • @MattBrauer 另一个 TableView 仅支持 QAbstractListModel 或从它们派生的类,多列思想基于角色。如果您查看文档,您将看到一个示例,然后您可以尝试在 python 中实现它:doc.qt.io/qt-5/qml-qtquick-controls-tableview.html
  • @eyllanesc 是否可以根据TableView 的宽度让所有列的宽度相等,而不是将每列的宽度硬编码为100?我将委托中的宽度定义为implicitWidth: tableView.width / tableView.model.columnCount() 的尝试仅部分有效。单击并拖动表格后,它将调整列的大小。
  • @roundtheworld 试试:columnWidthProvider: function (column) { tableView.width / tableView.model.columnCount(); }
  • 这不起作用...可能是因为我的TableiView 处于布局中...我将打开一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
相关资源
最近更新 更多