使用 PyQt/PySide 禁用 QTableWidget 中特定列中的排序箭头
Disable the sort arrow in a specific column in QTableWidget with PyQt/PySide
我想从第一列标题中删除箭头,使标题与复选框居中。所有这一切都没有禁用对列进行排序的可能性。
这是我当前的代码。
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QApplication,
QProxyStyle,
QStyle,
QTableWidget,
QTableWidgetItem,
)
class ProxyStyle(QProxyStyle):
def subElementRect(self, e, opt, widget):
r = super().subElementRect(e, opt, widget)
if e == QStyle.SE_ItemViewItemCheckIndicator:
r.moveCenter(opt.rect.center())
return r
class Table(QTableWidget):
def __init__(self):
QTableWidget.__init__(self, 3, 1)
self._style = ProxyStyle(self.style())
self.setStyle(self._style)
for i in range(self.rowCount()):
for j in range(self.columnCount()):
it = QTableWidgetItem()
self.setItem(i, j, it)
it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
it.setCheckState(Qt.Checked if (i + j) % 2 == 0 else Qt.Unchecked)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Table()
w.show()
sys.exit(app.exec_())
最简单的解决方案是覆盖 drawControl()
并将 QStyleOptionHeader 的 indicator
设置为 0(如果该列与您要隐藏的列匹配)。
class ProxyStyle(QProxyStyle):
# ...
def drawControl(self, ctl, opt, qp, widget=None):
if ctl == QStyle.CE_HeaderSection and opt.orientation == Qt.Horizontal:
if opt.section == widget.parent().property('hideSortIndicatorColumn'):
opt.sortIndicator = 0
super().drawControl(ctl, opt, qp, widget)
class Table(QTableWidget):
def __init__(self):
# ...
self.setProperty('hideSortIndicatorColumn', 0)
请注意,对于具有子项的复杂小部件,在小部件上设置样式并不总是足够的。
在你的情况下它起作用是因为你将当前样式添加到代理构造函数,但这意味着样式的所有权将 completely 由代理获取,并且任何其他 QWidget 将使用从那一刻开始代理(这几乎与将代理设置为整个应用程序相同)。
另一种方法是创建不带任何参数的代理(在这种情况下,将使用默认本机样式的 新实例),但这也意味着 no 小部件的子项将继承样式,因为 QStyles 不会传播给它们的子项。
我想从第一列标题中删除箭头,使标题与复选框居中。所有这一切都没有禁用对列进行排序的可能性。
这是我当前的代码。
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QApplication,
QProxyStyle,
QStyle,
QTableWidget,
QTableWidgetItem,
)
class ProxyStyle(QProxyStyle):
def subElementRect(self, e, opt, widget):
r = super().subElementRect(e, opt, widget)
if e == QStyle.SE_ItemViewItemCheckIndicator:
r.moveCenter(opt.rect.center())
return r
class Table(QTableWidget):
def __init__(self):
QTableWidget.__init__(self, 3, 1)
self._style = ProxyStyle(self.style())
self.setStyle(self._style)
for i in range(self.rowCount()):
for j in range(self.columnCount()):
it = QTableWidgetItem()
self.setItem(i, j, it)
it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
it.setCheckState(Qt.Checked if (i + j) % 2 == 0 else Qt.Unchecked)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Table()
w.show()
sys.exit(app.exec_())
最简单的解决方案是覆盖 drawControl()
并将 QStyleOptionHeader 的 indicator
设置为 0(如果该列与您要隐藏的列匹配)。
class ProxyStyle(QProxyStyle):
# ...
def drawControl(self, ctl, opt, qp, widget=None):
if ctl == QStyle.CE_HeaderSection and opt.orientation == Qt.Horizontal:
if opt.section == widget.parent().property('hideSortIndicatorColumn'):
opt.sortIndicator = 0
super().drawControl(ctl, opt, qp, widget)
class Table(QTableWidget):
def __init__(self):
# ...
self.setProperty('hideSortIndicatorColumn', 0)
请注意,对于具有子项的复杂小部件,在小部件上设置样式并不总是足够的。
在你的情况下它起作用是因为你将当前样式添加到代理构造函数,但这意味着样式的所有权将 completely 由代理获取,并且任何其他 QWidget 将使用从那一刻开始代理(这几乎与将代理设置为整个应用程序相同)。
另一种方法是创建不带任何参数的代理(在这种情况下,将使用默认本机样式的 新实例),但这也意味着 no 小部件的子项将继承样式,因为 QStyles 不会传播给它们的子项。