Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. TableView struggles
Forum Updated to NodeBB v4.3 + New Features

TableView struggles

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 2 Posters 202 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    gsal
    wrote last edited by
    #1

    I have spent a couple of afternoons, can't get it to work; I am just going in circles.

    Below, I will include both Python and QML sources of a minimal kind-of-working program.

    There are two features I can't figure out how to implement and I would very much appreciate some assistance.

    Desired features:

    • Keyboard navigation
    • Editing of cell values

    As follows:

    • When I click on a cell, I would like it to be highlighted in some way so I know where I am at.
    • After that, I would like to be able to use the tab key or the arrow keys to navigate the table.
    • When I double-click on a cell or press <enter> while highlighted, I would like for that cell to enter edit mode; and, most importantly (which is the part I can't get to work), when I leave edit mode, I would like the new value to be reflected in the table.

    Here is the Python code:

    import os
    import sys
    import json
    from pathlib import Path
    
    from PySide6.QtGui import QGuiApplication
    from PySide6.QtQml import QQmlApplicationEngine
    from PySide6.QtCore import (
        QAbstractTableModel, QModelIndex, QObject, Qt,
        Property, Signal, Slot
    )
    
    script_dir = Path( os.path.dirname(os.path.abspath(__file__)) )
    
    # --- MyTableModel ---
    # A custom model for use with QML's TableView.
    # It provides methods for reading, writing, and modifying table data.
    class MyTableModel(QAbstractTableModel):
        def __init__(self, header=None, data=None, parent=None):
            super().__init__(parent)
            self._header = header or []
            self._data = data or []
    
        def rowCount(self, parent=QModelIndex()):
            return len(self._data)
    
        def columnCount(self, parent=QModelIndex()):
            if self._data:
                return len(self._data[0])
            return 0
    
        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid():
                return None
            row = index.row()
            col = index.column()
            if row >= len(self._data) or col >= len(self._data[0]):
                return None
            if role == Qt.DisplayRole:
                return str(self._data[row][col])
    
        @Slot(int, Qt.Orientation, result="QVariant")
        def headerData(self, section, orientation, role=Qt.DisplayRole):
            if role == Qt.DisplayRole:
                if orientation == Qt.Horizontal:
                    return self._header[section]
                else:
                    return str(section)
    
        # required for editable models
        def setData(self, index, value, role=Qt.EditRole):
            if role == Qt.EditRole:
                if index.isValid() and 0 <= index.row() < self.rowCount() and 0 <= index.column() < self.columnCount():
                    row = index.row()
                    col = index.column()
                    self._data[row][col] = value
                    self.dataChanged.emit(index, index, [role])
                    return True
            return False
    
        # required for editable models, to inform the view which roles are editable
        def flags(self, index):
            if not index.isValid():
                return Qt.NoItemFlags
            return Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
    
    
    # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    # --- MyTableManager ---
    # A QObject that provides the interface between QML and MyTableModel.
    class MyTableManager(QObject):
        dataChanged = Signal()
    
        def __init__(self, model):
            super().__init__()
            self._model = model
            self._selected_row = -1
    
        @Property(QObject, constant=True)
        def model(self):
            return self._model
    
        @Slot(str)
        def loadData(self, filepath):
            self._model.loadData(filepath)
    
        @Slot(int, int, str)
        def updateValue(self, row, col, value):
            index = self._model.index(row, col, QModelIndex())
            self._model.setData(index, value)
    
    
    if __name__ == "__main__":
        app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()
    
        items = [
            [ "1", "Alice"  , "30"],
            [ "2", "Bob"    , "25"],
            [ "3", "Charlie", "35"]
        ]
        my_table_model = MyTableModel(data=items)
        manager = MyTableManager(my_table_model)
        engine.rootContext().setContextProperty("tableManager", manager)
        engine.rootContext().setContextProperty("tableModel", my_table_model)
    
        qml_file = Path(__file__).parent / "gen.qml"
        engine.load(qml_file)
        if not engine.rootObjects():
            sys.exit(-1)
    
        sys.exit(app.exec())
    
    

    Here is the QML source:

    import QtQuick
    import QtQuick.Controls.Basic
    
    Window {
        visible: true
        width: 320
        height: 180
        title: qsTr("Hello World")
        color: '#222222'
    
        TableView {
            id: tableView
            columnWidthProvider: function (column) { return 100; }
            rowHeightProvider: function (column) { return 40; }
            anchors.fill: parent
    
            model: tableModel
    
            delegate: Rectangle {
                implicitWidth: 100
                implicitHeight: 40
                color: (index % 2 === 0) ? "#FFFFFF" : "#F9F9F9"
                border.width: 1
                border.color: "lightgray"
                Text {
                    text: display
                    anchors.fill: parent
                    anchors.margins: 5
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                }
                TableView.editDelegate: TextField {
                    anchors.fill: parent
                    text: display
                    horizontalAlignment: TextInput.AlignHCenter
                    verticalAlignment: TextInput.AlignVCenter
                    TableView.onCommit: {
                        tableManager.updateValue(row, column, text)
                    }
                }
            }
        }
    }
    
    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bob64
      wrote last edited by
      #2

      For keyboard navigation, the documentation says to set the keyNavigationEnabled property to true. This needs at least Qt 6.4. It also says you need to assign an ItemSelectionModel to selectionModel.

      My recollection is that item selection models and their use are not particularly well documented in QML. See this forum post that might help: https://forum.qt.io/topic/133628/how-to-use-itemselectionmodel-with-tableview. It links to a Stack Overflow question that might also be useful.

      1 Reply Last reply
      0
      • G Offline
        G Offline
        gsal
        wrote last edited by
        #3

        Thanks for that, though, I did not get the answers I am looking for. This is very unfortunate and disappointing; I thought I read somewhere that Qt Quick/QML is supposed to be the next generation of QtWidgets?

        1 Reply Last reply
        0
        • G Offline
          G Offline
          gsal
          wrote last edited by
          #4

          Someone pointed me to the TableViewDelegate; I switched to that since it comes with the functionality that I need.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved