【问题标题】:How can you set header labels for QTableView columns?如何为 QTableView 列设置标题标签?
【发布时间】:2022-02-20 12:29:20
【问题描述】:

我正在使用 PyQt5 开发一个 Python GUI 应用程序,它有一个用于显示数据的 QTableView。

代码如下:

import sys

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt


class DataModel(QtCore.QAbstractTableModel):
    def __init__(self):
        super().__init__()
        self.data = []

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self.data[index.row()][index.column()]

    def rowCount(self, index):
        return len(self.data)

    def columnCount(self, index):
        return len(self.data[0])


class MainWindow(UI.UserInterface):
    def __init__(self):
        super().__init__()
        self.model = DataModel()
        self.load()
        self.TableView.setModel(self.model)
        self.TableView.resizeColumnsToContents()
        self.TableView.horizontalHeader().setStretchLastSection(True)

    def load(self):
        try:
            self.model.data = [(1, '2020-01-10 00:00:00', 'KANIA', 'HENRYK', 4219)]
        except Exception:
            pass


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec_()

UI.UserInterface 类位于单独的模块中。它有界面的QWidgets和布局QWidgets。其中之一是QTableView。

我似乎找不到为QTableView 设置标题标签的方法。

我寻找了不同的解决方案(其中一些如下),但都没有奏效:

https://doc.qt.io/qt-5/sql-presenting.html(这个是C++写的,不太明白)

【问题讨论】:

  • 在提供示例时请小心,并始终确保它们都是minimal and reproducible example,包括检查语法和不必要的导入。例如:sqlalchemy.sql 不是必需的,UserInterface 不是UI 的一部分,因为DataModel 不是Model 的一部分,Database.Base.metadata.create_all() 在示例范围内是不必要的。此外,您在 load 中的分配语法无效。

标签: python user-interface pyqt


【解决方案1】:

你必须实现headerData():

class DataModel(QtCore.QAbstractTableModel):
    # ...
    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return 'Column {}'.format(section + 1)
        return super().headerData(section, orientation, role)

显然,您甚至可以使用包含您要显示的标签的简单列表来设置自己的标签。

请注意,为子类命名新属性时应该非常小心,因为它们可能已经存在。
最重要的是,您应该不覆盖self.data。

【讨论】:

  • 有效!太感谢了。我一直在寻找这个 :) 在实际版本的代码中,我不会覆盖 self.data,我会附加它。这只是为了 Stackoverflow 的目的。
  • 您误会了:您应该不在您的班级中声明self.data = ... 根本,因为它已经存在,因为data() 是一个班级成员。在你的情况下,它只适用于一系列技术原因,我不会在这里解释。更改其名称,并通过查看有关 QAbstractTableModel 和 QAbstractItemModel 成员的文档来确保它不会覆盖其他现有属性。
【解决方案2】:

这是一个使用 QtableView 和 set headerdata 的示例,您将能够修改来自 tableview 的数据

def exemple_table(self):
        database = QSqlDatabase("QPSQL")
        database.setHostName("localhost")
        database.setDatabaseName("database")
        database.setUserName("postgres")
        database.setPassword("password")
        database.open()
        
        model_ft = QSqlTableModel(db=database)
        model_ft.setTable('table')
        
        model_ft.setHeaderData(0, Qt.Horizontal,"id")
        model_ft.setHeaderData(1, Qt.Horizontal,"exemple01")
        model_ft.setHeaderData(2, Qt.Horizontal,"exemple02")
        model_ft.setHeaderData(3, Qt.Horizontal,"exemple03")
        model_ft.setHeaderData(4, Qt.Horizontal,"exemple04")
        model_ft.setHeaderData(5, Qt.Horizontal,"exemple05")
        model_ft.setHeaderData(6, Qt.Horizontal,"exemple06")
        model_ft.setHeaderData(7, Qt.Horizontal,"exemple07")
        
        model_ft.removeColumns(8,1)
        date = str(datetime.date.today())
        
        self.tableView.setModel(model_ft)
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        model_ft.setSort(0, Qt.DescendingOrder)
        model_ft.select()
        filter_ft = "date_d ='%s' " % (date_1)
        model_ft.setFilter(filter_ft)

ps 我正在使用 postgresql,你可以在这里找到其他驱动程序 https://doc.qt.io/qt-5/sql-driver.html

还有你可以使用所有SQL函数的过滤器

【讨论】:

    【解决方案3】:

    覆盖QTableAbstractModel 的headerData 方法以设置列和行名称

    def headerData(self, section: int, orientation: PySide6.QtCore.Qt.Orientation, role: int = ...):
        #for setting columns name
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return f"Column {section + 1}"
        #for setting rows name
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return f"Row {section + 1}"
    

    工作代码:

    import sys
    import requests
    
    import PySide6
    from PySide6.QtWidgets import QTableView, QWidget, QApplication, QGridLayout, QHeaderView
    from PySide6.QtCore import Qt, QAbstractTableModel
    from PySide6.QtGui import QColor, QIcon, QPixmap
    
    from datetime import datetime
    
    
    class MagicIcon():
        def __init__(self, link):
            self.link = link
            self.icon = QIcon()
            try:
                response = requests.get(self.link)
                pixmap = QPixmap()
                pixmap.loadFromData(response.content)
                self.icon = QIcon(pixmap)
            except:
                pass
    
    
    class TableModel(QAbstractTableModel):
    
        def headerData(self, section: int, orientation: PySide6.QtCore.Qt.Orientation, role: int = ...):
            if orientation == Qt.Horizontal and role == Qt.DisplayRole:
                # return f"Column {section + 1}"
                return self.columns[section]
            if orientation == Qt.Vertical and role == Qt.DisplayRole:
                return f"{section + 1}"
    
        def __init__(self, _data):
            self.columns = ["Account", "Investment", "KYC", "Investment Date"]
            # super().__init__(self)
            super(TableModel, self).__init__()
            self._data = _data
            self.calendarLink = "https://img.icons8.com/fluency/48/000000/windows-calendar.png"
            self.dollarLink = "https://img.icons8.com/external-vitaliy-gorbachev-lineal-color-vitaly-gorbachev/40/000000/external-dollar-currency-vitaliy-gorbachev-lineal-color-vitaly-gorbachev-1.png"
            self.analysis = "https://img.icons8.com/external-flatarticons-blue-flatarticons/65/000000/external-analysis-digital-marketing-flatarticons-blue-flatarticons-1.png"
            self.bug = "https://img.icons8.com/offices/30/000000/bug.png"
            self.account = "https://img.icons8.com/plumpy/24/000000/edit-administrator.png"
            self.approvedLink = "https://img.icons8.com/external-bearicons-flat-bearicons/40/000000/external-approved-approved-and-rejected-bearicons-flat-bearicons-9.png"
            self.rejectedLink = "https://img.icons8.com/external-bearicons-flat-bearicons/40/000000/external-rejected-approved-and-rejected-bearicons-flat-bearicons-11.png"
            self.naLink = "https://img.icons8.com/color/48/000000/not-applicable.png"
    
            self.calendarIcon = MagicIcon(self.calendarLink).icon
            self.accountIcon = MagicIcon(self.account).icon
            self.dollarIcon = MagicIcon(self.dollarLink).icon
            self.approvedIcon = MagicIcon(self.approvedLink).icon
            self.rejectedIcon = MagicIcon(self.rejectedLink).icon
            self.naIcon = MagicIcon(self.naLink).icon
    
        def data(self, index, role):
            if role == Qt.DisplayRole:
                value = self._data[index.row()][index.column()]
                if isinstance(value, datetime):
                    return value.strftime("%Y-%m-%d")
                if isinstance(value, float):
                    return f"{value:.2f}"
                return value
            if role == Qt.TextAlignmentRole:
                return Qt.AlignHCenter + Qt.AlignVCenter
    
            if role == Qt.BackgroundRole:
                return QColor("#adcdff") if index.row() % 2 == 0 else QColor("#d8ffc2")
    
            if role == Qt.DecorationRole:
                value = self._data[index.row()][index.column()]
                
                if value is None:
                    return self.naIcon
                if isinstance(value, datetime):
                    return self.calendarIcon
                if index.column() == 0:
                    return self.accountIcon
                if index.column() == 1:
                    return self.dollarIcon
                if index.column() == 2:
                    if value == True:
                        return self.approvedIcon
                    elif value == False:
                        return self.rejectedIcon
                    return self.naIcon
    
        def rowCount(self, index):
            return len(self._data)
    
        def columnCount(self, index):
            return len(self._data[0])
    
    
    class MainWindow(QWidget):
        def __init__(self):
            # super().__init__()
            super(MainWindow, self).__init__()
            self.resizeEvent = self.onResize
            self.table = QTableView()
            
            self.setWindowIcon(MagicIcon(
                "https://img.icons8.com/external-flatarticons-blue-flatarticons/65/000000/external-analysis-digital-marketing-flatarticons-blue-flatarticons-1.png"
            ).icon)
    
            self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
            # self.table.setSizeAdjustPolicy(QHeaderView.AdjustIgnored)
            # self.table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
            data = [
                ["Andrew Mike", 15.255, True, datetime(2022, 1, 5)],
                ["Eliza Petterson", 353.555, False, datetime(2020, 1, 5)],
                ["Joseph Samuel", 123, None, datetime(2020, 1, 15)],
                ["Nita Singh", 266, True, datetime(2022, 2, 7)],
                ["Rahul Chakrabarti", 102, True, datetime(2019, 10, 15)],
            ]
            self.model = TableModel(data)
            self.table.setModel(self.model)
            self.header = self.table.horizontalHeader()
            # self.header.setSectionResizeMode(0, QHeaderView.Stretch)
            # self.header.setSectionResizeMode(1, QHeaderView.)
            # self.header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
            self.layout = QGridLayout()
            self.layout.addWidget(self.table, 0, 0)
            self.setLayout(self.layout)
    
        def onResize(self, event):
            # print('old', event.oldSize(), 'new', event.size())
            # super(MainWindow, self).resizeEvent(event)
            pass
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        wid = MainWindow()
        wid.show()
        sys.exit(app.exec())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多