1 2 3 4

使用pyqt实现官方例子QTableView的冻结行列

原理:使用三张表进行堆叠,在水平或者垂直滑动条的值发生变化时改变这三张表的堆叠顺序,使用stackUnder()进行堆叠顺序的改变

直接撸代码:

 

  1 import typing
  2 from PyQt5 import QtCore, QtGui
  3 from PyQt5.QtWidgets import QTableView, QAbstractItemView, QHeaderView, QAbstractSlider
  4 from PyQt5.QtCore import Qt, QModelIndex
  5 
  6 
  7 class FreezeTableView(QTableView, QAbstractSlider):
  8 
  9     def __init__(self, model):
 10         super(FreezeTableView, self).__init__()
 11         self.model = model
 12         self.frozenTableView = QTableView(self)
 13         self.horizontalView = QTableView(self)
 14         self.up = True
 15 
 16     def init(self):
 17         self.setModel(self.model)
 18         self.frozenTableInit()
 19         self.horizontalViewInit()
 20 
 21         self.horizontalHeader().sectionResized.connect(self.updateSectionWidth)
 22         self.verticalHeader().sectionResized.connect(self.updateSectionHeight)
 23         self.verticalScrollBar().valueChanged.connect(self.vConnectFV)
 24         self.frozenTableView.verticalScrollBar().valueChanged.connect(self.fVConnectV)
 25         self.horizontalScrollBar().valueChanged.connect(self.hConnectH)
 26 
 27     def vConnectFV(self, a0: int):
 28         self.viewport().stackUnder(self.frozenTableView)
 29         self.frozenTableView.stackUnder(self.horizontalView)
 30         self.frozenTableView.verticalScrollBar().setValue(a0)
 31 
 32     def fVConnectV(self, a0: int):
 33         self.viewport().stackUnder(self.frozenTableView)
 34         self.frozenTableView.stackUnder(self.horizontalView)
 35         self.verticalScrollBar().setValue(a0)
 36 
 37     def hConnectH(self, a0: int):
 38         self.viewport().stackUnder(self.horizontalView)
 39         self.horizontalView.stackUnder(self.frozenTableView)
 40         self.horizontalView.horizontalScrollBar().setValue(a0)
 41 
 42     def frozenTableInit(self):
 43         self.frozenTableView.setModel(self.model)
 44         self.frozenTableView.verticalHeader().hide()
 45         self.frozenTableView.setFocusPolicy(Qt.NoFocus)
 46         self.frozenTableView.horizontalHeader().setFixedHeight(self.horizontalHeader().height())
 47         self.frozenTableView.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
 48 
 49         self.viewport().stackUnder(self.frozenTableView)
 50         self.frozenTableView.setStyleSheet('QTableView {'
 51                                            'border: none;'
 52                                            'background-color: #8EDE21;'
 53                                            'selection-background-color: #999}')
 54         self.frozenTableView.setSelectionModel(self.selectionModel())
 55         [self.frozenTableView.setColumnHidden(col, True) for col in range(1, self.model.columnCount())]
 56         self.frozenTableView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
 57         self.frozenTableView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
 58         self.frozenTableView.show()
 59 
 60         self.updateFrozenTableGeometry()
 61         self.frozenTableView.setVerticalScrollMode(self.ScrollPerPixel)
 62         self.setVerticalScrollMode(self.ScrollPerPixel)
 63         self.setHorizontalScrollMode(self.ScrollPerPixel)
 64 
 65     def horizontalViewInit(self):
 66         self.horizontalView.setModel(self.model)
 67         self.horizontalView.horizontalHeader().hide()
 68         self.horizontalView.setFocusPolicy(Qt.NoFocus)
 69         self.horizontalView.verticalHeader().setFixedWidth(self.verticalHeader().width())
 70         self.horizontalView.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
 71 
 72         self.frozenTableView.stackUnder(self.horizontalView)
 73         self.horizontalView.setStyleSheet('QTableView { border: none;'
 74                                           'background-color: #8EDE21;'
 75                                           'selection-background-color: #999}')
 76         self.horizontalView.setSelectionModel(self.selectionModel())
 77         [self.horizontalView.setRowHidden(row, True) for row in range(1, self.model.rowCount())]
 78         self.horizontalView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
 79         self.horizontalView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
 80         self.horizontalView.show()
 81 
 82         self.updateFrozenTableGeometry()
 83         self.horizontalView.setHorizontalScrollMode(self.ScrollPerPixel)
 84 
 85     def updateFrozenTableGeometry(self):
 86         self.frozenTableView.setGeometry(self.verticalHeader().width() + self.frameWidth(),
 87                                          self.frameWidth(), self.columnWidth(0),
 88                                          self.viewport().height() + self.horizontalHeader().height())
 89         self.horizontalView.setGeometry(self.frameWidth(), self.frameWidth() + self.horizontalHeader().height(),
 90                                         self.viewport().width() + self.verticalHeader().width(), self.rowHeight(0))
 91 
 92     def updateSectionWidth(self, logicalIndex, oldSize, newSize):
 93         self.horizontalView.setColumnWidth(logicalIndex, newSize)
 94         if not logicalIndex:
 95             self.frozenTableView.setColumnWidth(0, newSize)
 96         self.updateFrozenTableGeometry()
 97 
 98     def updateSectionHeight(self, logicalIndex, oldSize, newSize):
 99         self.frozenTableView.setRowHeight(logicalIndex, newSize)
100         if not logicalIndex:
101             self.horizontalView.setRowHeight(0, newSize)
102         self.updateFrozenTableGeometry()
103 
104     def resizeEvent(self, e: QtGui.QResizeEvent) -> None:
105         QTableView.resizeEvent(self, e)
106         self.updateFrozenTableGeometry()
107 
108     def scrollTo(self, index: QtCore.QModelIndex, hint: QAbstractItemView.ScrollHint = ...) -> None:
109         if index.column() > 0 or index.row() > 0:
110             QTableView.scrollTo(self, index, hint)
111 
112     def moveCursor(self, cursorAction: QAbstractItemView.CursorAction,
113                    modifiers: typing.Union[QtCore.Qt.KeyboardModifiers,
114                                            QtCore.Qt.KeyboardModifier]) -> QtCore.QModelIndex:
115         current = QTableView.moveCursor(self, cursorAction, modifiers)
116         if cursorAction == QAbstractItemView.MoveLeft and current.column() > 0 \
117                 and self.visualRect(current).topLeft().x() < self.frozenTableView.columnWidth(0):
118             newValue = self.verticalScrollBar().value() + self.visualRect(current).topLeft().x() \
119                        - self.frozenTableView.columnWidth(0)
120             self.horizontalScrollBar().setValue(newValue)
121         if cursorAction == QAbstractItemView.MoveUp and current.row() > 0 \
122                 and self.visualRect(current).topLeft().y() < self.horizontalView.rowHeight(0):
123             newValue = self.horizontalScrollBar().value() + self.visualRect(current).topLeft().y() \
124                        - self.horizontalView.rowHeight(0)
125             self.verticalScrollBar().setValue(newValue)
126 
127         return current

 

具体完整代码,可以给git clone https://github.com/llkid/freezeWidget.git,c++实现也是通过该原理实现,有兴趣的可以尝试写一下。

 

posted on 2020-10-06 10:40  可爱的Snoopy  阅读(2138)  评论(0编辑  收藏  举报

Live2D