如何设置整行而不是所有单元格的样式
Posted
技术标签:
【中文标题】如何设置整行而不是所有单元格的样式【英文标题】:how to style the entire line instead of all cells 【发布时间】:2021-03-29 01:08:47 【问题描述】:我需要将 QTableWidget 的线四舍五入,使其看起来像这样,
但是当尝试设置边界半径时,它会修改所有单元格 像这样。
我几乎没有发现非 C++ 编写的表格样式 或者解释表中行的样式化
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 303)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.tableWidget = QtWidgets.QTableWidget(Form)
self.tableWidget.setStyleSheet("QTableWidget\n"
"background-color: white;\n"
"color:black;\n"
"border-bottom: 2px solid white;\n"
"border-right: 2px solid white;\n"
"\n"
"\n"
"QTableView::item \n"
"border-bottom: 1px solid #d6d9dc;\n"
"border-top: 1px solid #d6d9dc;\n"
"margin-bottom:5px;\n"
"border-radius:10px;\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"QTableView::section\n"
"color:blue;\n"
"")
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(2)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
self.tableWidget.horizontalHeader().setVisible(False)
self.tableWidget.verticalHeader().setVisible(False)
self.horizontalLayout.addWidget(self.tableWidget)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("Form", "New Row"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("Form", "New Row"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Form", "New Column"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("Form", "New Column"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("Form", "New Column"))
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_())
上面的代码有什么问题?
【问题讨论】:
请不要将代码(包括样式表)作为图片发布,因为这会使试图重现您的问题非常烦人,因为我们需要手动复制所有内容(我们可能会犯一些错误或遗漏一些你的)。也就是说,该样式表是为表设置的还是为任何父级设置的?您确定没有在任何父小部件(包括窗口)上设置另一个(可能是通用的)样式表吗?我建议你包含 ui 文件的完整代码。 请提供minimal reproducible example M.R.E 已经在这个问题上了,抱歉之前没有发布过 @PeterTorben 抱歉,我误读了您的问题,因为我认为问题与表格的圆形边框有关。 【参考方案1】:我认为通过设置表格小部件的样式表是不可能的,但可以通过将表格的项目委托设置为自定义QStyledItemDelegate
来覆盖paint
和sizeHint
,例如
from PyQt5 import QtCore, QtGui, QtWidgets
class MyStyledItem(QtWidgets.QStyledItemDelegate):
def __init__(self, margin, radius, border_color, border_width, parent=None):
"""
margin: distance between border and top of cell
radius: radius of rounded corner
border_color: color of border
border_width: width of border
"""
super().__init__(parent)
self.margin = margin
self.radius = radius
self.border_color = border_color
self.border_width = border_width
def sizeHint(self, option, index):
# increase original sizeHint to accommodate space needed for border
size = super().sizeHint(option, index)
size = size.grownBy(QtCore.QMargins(0, self.margin, 0, self.margin))
return size
def paint(self, painter, option, index):
painter.save()
painter.setRenderHint(painter.Antialiasing)
# set clipping rect of painter to avoid painting outside the borders
painter.setClipping(True)
painter.setClipRect(option.rect)
# call original paint method where option.rect is adjusted to account for border
option.rect.adjust(0, self.margin, 0, -self.margin)
super().paint(painter, option, index)
pen = painter.pen()
pen.setColor(self.border_color)
pen.setWidth(self.border_width)
painter.setPen(pen)
# draw either rounded rect for items in first or last column or ordinary rect
if index.column() == 0:
rect = option.rect.adjusted(self.border_width, 0, self.radius + self.border_width, 0)
painter.drawRoundedRect(rect, self.radius, self.radius)
elif index.column() == index.model().columnCount(index.parent()) - 1:
rect = option.rect.adjusted(-self.radius-self.border_width, 0, -self.border_width, 0)
painter.drawRoundedRect(rect, self.radius, self.radius)
else:
rect = option.rect.adjusted(-self.border_width, 0, self.border_width, 0)
painter.drawRect(rect)
# draw lines between columns
if index.column() > 0:
painter.drawLine(option.rect.topLeft(), option.rect.bottomLeft())
painter.restore()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
# create test table
table = QtWidgets.QTableWidget()
table.setRowCount(3)
table.setColumnCount(3)
for row in range(table.rowCount()):
for col in range(table.columnCount()):
table.setItem(row, col, QtWidgets.QTableWidgetItem(f'item at row=, col='))
table.setShowGrid(False)
delegate = MyStyledItem(margin=3, radius=10, border_width=2, border_color=QtGui.QColor("navy"))
table.setItemDelegate(delegate)
# the custom styled item delegate can be used with a style sheet
table.setStyleSheet("QTableView::item border: 0px; padding: 10px; ")
# next line is needed to call the sizeHint of the item delegate
table.resizeRowsToContents()
table.show()
app.exec()
截图:
【讨论】:
感谢您的回答,我从来没有在 pyqt5 中遇到过委托,这是一个很棒的学习。以上是关于如何设置整行而不是所有单元格的样式的主要内容,如果未能解决你的问题,请参考以下文章