控制QTreeView标头中的网格线和边框的显示

问题描述

(W10平台)

我想要得到的(我被要求用Gimp产生目标结果):

what I want

我目前得到的是什么

current result

MRE:

new_df = df.loc[(df['Dateddiff'].le(28) &
                 df['Indicator'].eq('Y')).groupby(df['ID'])
                                         .transform('any')]
print(new_df)

    ID Indicator  Dateddiff
0  111         N          0
1  111         Y         10
2  111         N         32
7  114         Y          0
8  114         N         28

我要在这里做的是1)更改水平标题中的网格线; 2)在表头和数据行之间放置某种实线。如果有兴趣,请取消注释我的尝试。

我不清楚是否要使用from PyQt5.QtCore import QRect,Qt,QAbstractTableModel from PyQt5.QtWidgets import QApplication,QMainWindow,QTableView,QWidget,QVBoxLayout,qstyledItemDelegate,\ QPlainTextEdit,QShortcut import sys,types from PyQt5.QtGui import QFont,QBrush,QColor class HistoryTableModel( QAbstractTableModel ): def __init__( self ): super(HistoryTableModel,self).__init__() data = [ [4,9,2],[1,0],[3,5,] self._data = 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 2 def flags(self,index): return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable def setData(self,value,role ): if role == Qt.EditRole: self._data[ index.row() ][ index.column() ] = value return True def headerData(self,section,orientation,role): if orientation == Qt.Horizontal: print( f'headerData,horiz: section {section},role {role}') if role == Qt.displayRole: return ( 'Date','Entry' )[section] elif role == Qt.ForegroundRole: # this has the desired effect: colours the font result = super().headerData( section,role ) return QBrush( QColor( 'brown' ) ) elif role == Qt.BackgroundRole: # this seems to have no effect result = super().headerData( section,role ) return QBrush( QColor( 'yellow' ) ) class Ui_MainWindow(object): def setupUi(self,MainWindow): MainWindow.resize(600,700 ) self.centralwidget = QWidget(MainWindow) self.verticalLayoutWidget = QWidget(self.centralwidget) self.verticalLayoutWidget.setGeometry( QRect(20,20,300,300)) self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) self.comps = [] self.table_view = QTableView(self.verticalLayoutWidget) # this has an effect on the table data rows,but it's the header I want to format... self.table_view.setStyleSheet( 'background: palegoldenrod; gridline-color: black;' ) # # ATTEMPT 1 # # this has an inexplicable effect: most of the window outside the table is given a white background; # # gridlines are unchanged # self.table_view.setStyleSheet( """QTableHeader.section.horizontal { # color: red; # background: blue; # gridline-color: green; # }""" ) # # ATTEMPT 2 # # this puts a small corner of blue in the top right corner of the window; # # gridlines are unchanged # self.table_view.horizontalHeader().setStyleSheet( """ # color: red; # background: blue; # gridline-color: green; # """ ) # # ATTEMPT 3 # # this puts a small line of red in the top right corner of the window; # self.table_view.horizontalHeader().setStyleSheet( """ # border-bottom:3px solid red; # """ ) self.comps.append( self.table_view ) self.table_view.setGeometry(QRect(20,200,200)) self.verticalLayout.addWidget(self.table_view) self.table_view.setModel( HistoryTableModel() ) MainWindow.setCentralWidget(self.centralwidget) class MainWindow(QMainWindow): def __init__(self): super(MainWindow,self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) app = QApplication(sys.argv) application = MainWindow() application.show() sys.exit(app.exec()) 的替代功能是这里的解决方法:我看不到该功能实际上是如何处理网格线的……或者样式表是否应该做到这一点。

在W10机器上工作似乎很重要(即,在Linux / OS中可能会获得更容易理解的结果)。

尝试1的图片

failed attempt 1

尝试2的图片

failed attempt 2

尝试3的图片

failed attempt 3

解决方法

您要样式化的是表 header (一个QHeaderView),而不是表。

因此,您应该将样式表应用于样式表,并使用正确的class::selector:state语法。

table.horizontalHeader().setStyleSheet('''
    QHeaderView {
        /* set the bottom border of the header,in order to set a single 
           border you must declare a generic border first or set all other 
           borders */
        border: none;
        border-bottom: 2px solid green;
    }

    QHeaderView::section:horizontal {
        /* set the right border (as before,the overall border must be 
           declared),and a minimum height,otherwise it will default to 
           the minimum required height based on the contents (font and 
           decoration sizes) */
        border: none;
        border-right: 1px solid red;
        min-height: 28px;
    }
''')

请注意,由于在示例中我已将样式表设置为水平标题,因此可以省略:horizontal选择器(但必须使用::section)。

还要考虑您仍然可以在表格上设置上面的样式表:由于我正确使用了类选择器,因此可以正确应用其语法。问题在于,由于我们需要为整个标头显示边框,因此必须将其应用于没有选择器的类,这显然会导致 both 标头显示底部边框,这是因为在这种情况下,:horizontal无法正常工作(AFAIK)。