调整 QTableWidget 单元格和 header 项中的缩进

Adjust indents in QTableWidget cells and header items

我想在左侧对齐 QTableWidget 中的文本,但我还想添加一个缩进,这样文本就不会卡在边框上。在图像上, col_2 是我想要的。我希望 header 标签也一样。

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTableWidgetItem

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setObjectName("gridLayout")
        self.tableWidget = QtWidgets.QTableWidget(Form)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

        self.tableWidget.setRowCount(0)
        self.tableWidget.setColumnCount(2)
        entries = ['aa','bb','cc','dd','ee']
        for row, form in enumerate(entries):
            self.tableWidget.insertRow(row)
            for column, item in enumerate(form):
                self.tableWidget.setItem(row, column, QTableWidgetItem(str(item)))

        self.tableWidget.setHorizontalHeaderLabels(['col_1', 'col_2'])

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

对于缩进,QSS Reference suggests that it should be possible to use the QTableWidget::item and QHeaderView::section 选择器:

self.tableWidget.setStyleSheet("""
    QTableWidget::item {padding-left: 5px; border: 0px}
    """)

self.tableWidget.horizontalHeader().setStyleSheet("""
    QHeaderView::section {padding-left: 5px; border: 0px}
    """)

但是,我尝试了各种填充、边距和边框设置的组合,发现它们要么根本不起作用,要么怪异难看side-effects。在查看了 SO 和其他地方的几个类似问题之后,这些样式表设置的确切行为似乎取决于您使用的平台 and/or 您使用的是什么 widget-style。希望它们能为您正常工作,但如果您发现一些小问题,请不要感到惊讶。

如果样式表解决方案不起作用,大多数人会使用自定义 item-delegate。这通常涉及重新实现 paint method. However, an alternative approach would be to reimplement the displayText method and pad the returned text with spaces. This does not affect the underlying data at all, and gives completely equivalent results in a much simpler way. It is also quite simple to reimplement the createEditor 方法,以便在编辑单元格时调整左边距。完整的自定义 item-delegate 将如下所示:

class PaddingDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, padding=1, parent=None):
        super(PaddingDelegate, self).__init__(parent)
        self._padding = ' ' * max(1, padding)

    def displayText(self, text, locale):
        return self._padding + text

    def createEditor(self, parent, option, index):
        editor = super().createEditor(parent, option, index)
        margins = editor.textMargins()
        padding = editor.fontMetrics().width(self._padding) + 1
        margins.setLeft(margins.left() + padding)
        editor.setTextMargins(margins)
        return editor

并且可以这样使用:

self.delegate = PaddingDelegate()
self.tableWidget.setItemDelegate(self.delegate)

拼图的最后一块是 header 项的缩进。为此,在标签文本中添加一些空格似乎最简单:

self.tableWidget.setHorizontalHeaderLabels([' col_1', ' col_2'])

header 标签的对齐方式可以这样设置:

self.tableWidget.horizontalHeader().setDefaultAlignment(
    QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)