【问题标题】:How can i remove the outside gridlines of QTableWidget and QHeaderView?如何删除 QTableWidget 和 QHeaderView 的外部网格线?
【发布时间】:2021-11-03 15:57:33
【问题描述】:

我想创建一个自定义 QTableView,我不想为其显示外部网格线,这意味着省略每个单元格的底部和右侧线。使用样式表,我似乎只能更改网格线颜色和 QHeaderView 的边框。我还想让网格线更粗一些,并且以某种方式只能查看内部线。

当前样式表:

QTableWidget {
padding-left: 50px;
padding-right: 50px;
gridline-color: #9370DB;
}


QHeaderView::section:vertical { 
border-top: 1px solid #9370DB
}

QHeaderView::section:horizontal { 
border: 0px;
border-left: 1px solid #9370DB
}

当前输出如下所示:

我还可以看到标题线和网格线未对齐,但这可以通过在任何地方使用相同的线粗来解决。

完整的测试代码:

from PySide6.QtCore import *  # type: ignore
from PySide6.QtGui import *  # type: ignore
from PySide6.QtWidgets import *  # type: ignore
import sys


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.verticalLayout_2 = QVBoxLayout(self.centralwidget)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.indicatorsLayout = QHBoxLayout()
        self.indicatorsLayout.setObjectName(u"indicatorsLayout")

        self.verticalLayout_2.addLayout(self.indicatorsLayout)

        self.listboxLayout = QGridLayout()
        self.listboxLayout.setObjectName(u"listboxLayout")
        self.listbox = QTableWidget(self.centralwidget)
        if (self.listbox.columnCount() < 5):
            self.listbox.setColumnCount(5)
        if (self.listbox.rowCount() < 10):
            self.listbox.setRowCount(10)
        self.listbox.setObjectName(u"listbox")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.listbox.sizePolicy().hasHeightForWidth())
        self.listbox.setSizePolicy(sizePolicy)
        self.listbox.setStyleSheet(u"QTableWidget {\n"
                                   "padding-left: 50px;\n"
                                   "padding-right: 50px;\n"
                                   "gridline-color: #9370DB;\n"
                                   "}\n"
                                   "\n"
                                   "\n"
                                   "QHeaderView::section:vertical { \n"
                                   "border-top: 1px solid #9370DB\n"
                                   "}\n"
                                   "\n"
                                   "QHeaderView::section:horizontal { \n"
                                   "border: 0px;\n"
                                   "border-left: 1px solid #9370DB\n"
                                   "}")
        self.listbox.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.listbox.setSizeAdjustPolicy(QAbstractScrollArea.AdjustIgnored)
        self.listbox.setRowCount(10)
        self.listbox.setColumnCount(5)
        self.listbox.horizontalHeader().setCascadingSectionResizes(False)
        self.listbox.horizontalHeader().setDefaultSectionSize(100)

        self.listboxLayout.addWidget(self.listbox, 0, 0, 1, 1)

        self.verticalLayout_2.addLayout(self.listboxLayout)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 22))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)

    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
    # retranslateUi


if __name__ == "__main__":
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec())

【问题讨论】:

  • 你能澄清一下“不显示外部网格线”是什么意思吗?你的意思是不想看到最后一行和最后一列的底线和右边线?
  • @musicamante 是的,对不起。我将编辑我的帖子以使其更清晰。它应该看起来像井字游戏网格

标签: qt pyqt5 qt-designer


【解决方案1】:

网格线的宽度始终为 1 像素,并且无法更改。未对齐是由于网格线始终绘制在每个索引的底部和右侧,而您将标题的边框设置在每个部分的顶部或左侧。

这也意味着网格线总是显示在所有项目周围,包括最后一行和最后一列。

解决方案是完全禁用网格,并仅以与绘制标题相同的方式设置项目的边框;这样,还可以设置“网格”的粗细。这种方法的缺点是项目的样式会覆盖委托的默认样式绘制,因此您还必须指定选择颜色。

QTableWidget {
    qproperty-showGrid: "false";
    padding-left: 50px;
    padding-right: 50px;
}

QTableWidget::item {
    border-top: 2px solid #9370DB;
    border-left: 2px solid #9370DB;
}

QTableWidget::item:selected {
    background: palette(highlight);
}


QHeaderView::section:vertical { 
    border: 0px;
    border-top: 2px solid #9370DB
}

QHeaderView::section:horizontal { 
    border: 0px;
    border-left: 2px solid #9370DB
}

稍微不同的方法同时使用样式表项目委托:绘制所有边框(使用所需大小的一半),不包括标题的最后一部分,并且使用绘制网格委托,在这种情况下,样式::item 选择器设置,确保它始终尊重样式提供的内部呈现。

class GridDelegate(QtWidgets.QStyledItemDelegate):
    pen = QtGui.QPen(QtGui.QColor('#9370DB'), 1)

    def paint(self, qp, opt, index):
        qp.save()
        qp.setPen(self.pen)
        qp.setBrush(QtCore.Qt.NoBrush)
        lastRow = index.model().rowCount() - 1
        lastCol = index.model().columnCount() - 1
        if index.row() < lastRow and index.column() < lastCol:
            qp.drawRect(opt.rect.adjusted(0, 0, -1, -1))
        else:
            qp.drawLine(opt.rect.bottomLeft(), opt.rect.topLeft())
            qp.drawLine(opt.rect.topLeft(), opt.rect.topRight())
            if index.row() < lastRow:
                qp.drawLine(opt.rect.bottomLeft(), opt.rect.bottomRight())
            elif index.column() < lastCol:
                qp.drawLine(opt.rect.topRight(), opt.rect.bottomRight())
        qp.restore()
        super().paint(qp, opt, index)


# ...
tableWidget.setItemDelegate(GridDelegate(tableWidget))
tableWidget.setStyleSheet('''
    QTableWidget {
        qproperty-showGrid: "false"; 
        padding-left: 50px; 
        padding-right: 50px; 
    }

    QTableCornerButton::section { 
        border: 0px; 
        border-bottom: 1px solid #A370DB; 
        border-right: 1px solid #A370DB; 
    }

    QHeaderView::section:vertical { 
        border: 1px solid #9370DB; 
        border-left: none; 
    }

    QHeaderView::section:vertical:last { 
        border-bottom: none; 
    }

    QHeaderView::section:horizontal { 
        border: 1px solid #9370DB; 
        border-top: none; 
    }

    QHeaderView::section:horizontal:last { 
        border-right: none; 
    }
''')

【讨论】:

  • 非常感谢!我错过了我可以使用边框来绘制网格而不是网格本身的事实。
  • @conopizda2 不客气。我已经更新了答案,包括一种稍微不同的方法来确保风格的一致性。
猜你喜欢
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多