Автоматическое заполнение столбцов таблицы

#python #pyqt5 #qml

Вопрос:

У меня есть приложение, которое использует PyQt5, у него есть табличное представление в QML, которое берет данные из фрейма данных pandas.

Мне нужна ширина столбцов, чтобы автоматически соответствовать ширине содержимого при каждом обновлении данных с новой загрузкой фреймов данных. Я не нашел ничего нового по этой теме на форумах, и старые ответы очень запутанны, я не могу поверить, что в 2021 году не будет простого решения для чего-то столь распространенного в табличных процедурах.

Код QML, который у меня есть, выглядит следующим образом:

 TableView {
  id: tableView
  antialiasing: true
  width: parent.width
  height: parent.height
  columnWidthProvider: function (column) { return 200; }
  rowHeightProvider: function (column) { return 60; }
  leftMargin: rowsHeader.implicitWidth
  topMargin: columnsHeader.implicitHeight
  rightMargin: columnsHeader.implicitHeight
  Layout.fillHeight: true
  model: table_model
  delegate: Rectangle {
    color: "transparent"
    Text {
      text: display
      anchors.fill: parent
      anchors.margins: 10
      horizontalAlignment: Text.AlignHCenter
      color: {
        if (temaescolhido.currentText == 'Claro') return 'Black'
          return 'White'
      }
      font.pixelSize: 15
      verticalAlignment: Text.AlignVCenter
    }
  }
  Rectangle { // mask the headers
    z: 3
    color: "transparent"
    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: table_model.headData(modelData, Qt.Horizontal)
        color: 'green'
        font.bold: true
        font.pixelSize: 15
        padding: 10
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
        background: Rectangle { color: "#adadad" }
      }
    }
  }
  Column {
    id: rowsHeader
    x: tableView.contentX
    z: 2
    Repeater {
      model: tableView.rows > 0 ? tableView.rows : 1
      Label {
        width: 35
        height: tableView.rowHeightProvider(modelData)
        text: table_model.headData(modelData, Qt.Vertical)
        color: 'green'
        font.bold: true
        font.pixelSize: 15
        padding: 10
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
        background: Rectangle { color: "#adadad" }
      }
    }
  }

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

Комментарии:

1. старые ответы, вероятно, сбивают с толку, потому что табличное представление было официально добавлено только в версии 2.12, до этого мы создавали большинство таблиц с помощью ListView. Я попробую ответить, если у меня будет время. Эта функция изменилась между версиями с 5.12 по 5.15, поэтому, чтобы предоставить что-то полезное, на какую версию Qt (или PyQt5) вы нацелены?

2. Привет, спасибо за ответ. Я использую qt 5.15.4 с Qtquick. Но я рассматриваю возможность использования qtwidgets, чтобы иметь возможность выполнять весь код на python (без qml), так как у меня больше знаний на этом языке. Как вы думаете, я бы слишком много потерял в возможностях создания, переключившись с qtquick на qtwidgets?

3. Я не думаю, что есть простой ответ на виджеты vs Quick. В Quick есть анимации, которые используют OpenGL для использования 3D-графического процессора, но я читал, что виджеты лучше интегрированы с matplotlib, так что все зависит от того, что вы пытаетесь сделать

Ответ №1:

Идея нового TableView состоит в том, чтобы установить неявную ширину и неявную высоту делегатов, а затем TableView должен автоматически определять размер строк и столбцов.

Вот тривиальный пример:

введите описание изображения здесь

 import QtQuick 2.15
import QtQuick.Controls 2.15
import Qt.labs.qmlmodels 1.0

ApplicationWindow {
    id: window
    visible: true
    width: 500
    height: 500

    Row {
        id: buttons
        Button {
            text: "Press To Add Data"
            onClicked: {
                var index = myTableModel.rowCount   1
                myTableModel.insertRow(0, {
                    "col 0": (1000000 index).toString(),
                    "col 1": index.toString().repeat(index)
                })
            }
        }

        Item {
            // button spacer
            width: 5
            height: 5
        }

        Button {
            text: "Press To Clear Data"
            onClicked: {
                myTableModel.removeRow(0)
            }
        }
    }

    TableView {
        id: tableView

        y: buttons.height
        height: parent.height - buttons.height
        width: parent.width

        columnSpacing: 0
        rowSpacing: 0
        clip: true

        model: TableModel {
            id: myTableModel
            TableModelColumn { display: "col 0" }
            TableModelColumn { display: "col 1" }

            rows: [
                {
                    "col 0": "0",
                    "col 1": "1"
                },
                {
                    "col 0": "2",
                    "col 1": "3"
                },
                {
                    "col 0": "4",
                    "col 1": "5"
                }
            ]
        }

        delegate: Rectangle {
            implicitWidth: childrenRect.width
            implicitHeight: childrenRect.height
            border.width: 1

            Text {
                padding: 5
                text: display
            }
        }
    }
}