python - 如何将 PyQt5 QTableView 的verticalHeader 移动到右侧?
问题描述
我想重新排列我的 QTableView 以便verticalHeader 出现在右侧,如下所示:
我尝试使用布局小部件进行此操作,但下面的代码给了我这个...
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QModelIndex, Qt
import sys
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, data=[[]], parent=None):
super().__init__(parent)
self.data = data
def headerData(self, section: int, orientation: Qt.Orientation, role: int):
if role == QtCore.Qt.DisplayRole:
if orientation == Qt.Horizontal:
return "Column " + str(section)
else:
return "Row " + str(section)
def columnCount(self, parent=None):
return len(self.data[0])
def rowCount(self, parent=None):
return len(self.data)
def data(self, index: QModelIndex, role: int):
if role == QtCore.Qt.DisplayRole:
row = index.row()
col = index.column()
return str(self.data[row][col])
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
data = [[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25],
[31, 32, 33, 34, 35]]
model = MyTableModel(data)
view = QtWidgets.QTableView()
view.setModel(model)
gridLayout = QtWidgets.QGridLayout()
gridLayout.addWidget(view, 0, 0, 1, 1)
gridLayout.addWidget(view.verticalHeader(), 0, 1, 1, 1)
container = QtWidgets.QWidget()
container.setLayout(gridLayout)
container.show()
sys.exit(app.exec_())
解决方案
一个基本(但不完美)的解决方案是将layoutDirection
小部件设置为RightToLeft
:
view.setLayoutDirection(QtCore.Qt.RightToLeft)
如果您仍然想保持文本向左对齐,您可以返回相反的布局方向TextAlignmentRole
(文本对齐相对于layoutDirection
,所以如果是RightToLeft
,返回左对齐会导致右对齐):
def data(self, index: QModelIndex, role: int):
# ...
if role == QtCore.Qt.TextAlignmentRole:
return QtCore.Qt.AlignRight
正如评论中所指出的,这有一些缺点:整个水平布局系统将被反转,这可能会导致用户出现意外行为。
您当然不应该尝试通过将项目视图的标题添加到另一个小部件的布局来重新设置或移动它,因为它不会按预期工作。
滚动区域有一个setViewportMargins()
功能,但对于项目视图来说总是被覆盖(因为它用于根据标题的内容设置边距)。
一个可能的(并且显然比上面更好)的解决方案是对表进行子类化并覆盖updateGeometries()
函数,以便我们可以在setViewportMargins()
之后调用.
之后,您必须手动设置两个标题的几何形状,并确保私有角落小部件(用于选择表中所有项目的左上角“隐藏”按钮)正确定位。
class RightHeaderTable(QtWidgets.QTableView):
def __init__(self):
super().__init__()
self._cornerButton = self.findChild(QtWidgets.QAbstractButton)
self._geometryRecursionBlock = False
def updateGeometries(self):
super().updateGeometries()
# avoid recursive calls (important for interactively resized columns)
if self._geometryRecursionBlock:
return
self._geometryRecursionBlock = True
margins = self.viewportMargins()
left = margins.left()
margins.setRight(left)
margins.setLeft(0)
self.setViewportMargins(margins)
vHeader = self.verticalHeader()
geo = vHeader.geometry()
geo.moveRight(self.viewport().geometry().right() + left)
vHeader.setGeometry(geo)
hHeader = self.horizontalHeader()
geo = hHeader.geometry()
geo.moveLeft(self.viewport().geometry().left())
hHeader.setGeometry(geo)
self._cornerButton.move(geo.width(), 0)
self._geometryRecursionBlock = False
请注意,这是一个非常基本的实现。您可能会注意到一些意想不到的行为。
推荐阅读
- google-cloud-platform - 如何查看 Google Cloud Function 实例使用的 IP 地址?
- android - Google play:突出披露中缺少信息
- python - 在 python tkinter 中销毁 GUI 窗口
- javascript - 为什么我用来显示/隐藏 div 的 javascript 在 IE 中不起作用?
- html - 响应式配置器的问题
- kubernetes - Kubernetes Service ping 不时工作“名称解析暂时失败”
- bash - 获取子网 ID AWS
- r - 枢轴加宽表 dyplr R
- intel - mem_load_uops_retired.l3_miss 和 offcore_response.demand_data_rd.l3_miss.local_dram 事件之间的区别
- javascript - fullcalendar 通过悬停在当天添加工具提示