使用 QTableView 和 QSelectionModel 选择日历样式

我正在使用 QTableView 构建自定义日历视图,并希望有一个 QItemSelectionModel 可以按天和周连续选择单元格。不确定从哪里开始,因为选择模型不与视图交互。视图的 onCurrentChange 方法提供当前索引,在 selectionModel 中不起作用。


视图通常连接到更复杂的日历模型;这里的表格模型是为了说明。


from PyQt5.QtCore import QModelIndex, QDate

from PyQt5.QtCore import Qt, QAbstractTableModel, QItemSelectionModel


from PyQt5.QtWidgets import QTableView

import typing



class TableModel(QAbstractTableModel):

    def __init__(self):

        super(TableModel, self).__init__()


    def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:

        if orientation == Qt.Horizontal and role == Qt.DisplayRole:

            return QDate.longDayName(section + 1)


    def data(self, index, role):

        if role == Qt.DisplayRole:

            return index.row() * 7 + index.column() + 1


    def rowCount(self, index):

        return 6


    def columnCount(self, index):

        return 7



class CalendarSelectionModel(QItemSelectionModel):


    def __init__(self, *args, **kwargs):

        super(CalendarSelectionModel, self).__init__(*args, *kwargs)


    def currentChanged(self, current: QModelIndex, previous: QModelIndex) -> None:

        print(current, previous)



class CalendarView(QTableView):


    def __init__(self):

        super(CalendarView, self).__init__()


    # def currentChanged(self, current: QModelIndex, previous: QModelIndex) -> None:

    #     print(current)



if __name__ == '__main__':

    import sys

    from PyQt5.QtWidgets import QApplication, QTableView


    app = QApplication(sys.argv)


    model = TableModel()


    cal = CalendarView()

    cal.setModel(model)

    sel = CalendarSelectionModel(model)

    cal.setSelectionModel(sel)

    cal.show()


    cal.resize(860, 640)


    sys.exit(app.exec_())



慕尼黑8549860
浏览 112回答 1
1回答

Qyouu

这是日历样式选择的解决方案。在表格上设置 QAbstractItemView.NoSelection 并将选择逻辑放在 currentChanged 中是一种方法。import typingfrom PyQt5.QtCore import QDatefrom PyQt5.QtCore import Qt, QAbstractTableModel, QItemSelectionModel, QItemSelection, QModelIndexfrom PyQt5.QtGui import QMouseEventfrom PyQt5.QtWidgets import QTableView, QAbstractItemViewclass TableModel(QAbstractTableModel):&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; super(TableModel, self).__init__()&nbsp; &nbsp; def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:&nbsp; &nbsp; &nbsp; &nbsp; if orientation == Qt.Horizontal and role == Qt.DisplayRole:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return QDate.longDayName(section + 1)&nbsp; &nbsp; def data(self, index, role):&nbsp; &nbsp; &nbsp; &nbsp; if role == Qt.DisplayRole:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return index.row() * 7 + index.column() + 1&nbsp; &nbsp; def rowCount(self, index):&nbsp; &nbsp; &nbsp; &nbsp; return 6&nbsp; &nbsp; def columnCount(self, index):&nbsp; &nbsp; &nbsp; &nbsp; return 7class CalendarView(QTableView):&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; super(CalendarView, self).__init__()&nbsp; &nbsp; &nbsp; &nbsp; self.setSelectionMode(QAbstractItemView.NoSelection)&nbsp; &nbsp; &nbsp; &nbsp; self._start: typing.Union[QModelIndex, None] = None&nbsp; &nbsp; def mousePressEvent(self, e: QMouseEvent) -> None:&nbsp; &nbsp; &nbsp; &nbsp; self._start = self.indexAt(e.pos())&nbsp; &nbsp; &nbsp; &nbsp; self.clearSelection()&nbsp; &nbsp; &nbsp; &nbsp; self.selectionModel().select(self._start, QItemSelectionModel.Select)&nbsp; &nbsp; &nbsp; &nbsp; super(CalendarView, self).mousePressEvent(e)&nbsp; &nbsp; def index(self, row, col):&nbsp; &nbsp; &nbsp; &nbsp; return self.model().index(row, col)&nbsp; &nbsp; def currentChanged(self, current: QModelIndex, previous: QModelIndex) -> None:&nbsp; &nbsp; &nbsp; &nbsp; if self.state() == QAbstractItemView.DragSelectingState:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.clearSelection()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if current.row() == self._start.row():&nbsp; # we only have one row, select from start to current&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection = QItemSelection(self._start, self.model().index(self._start.row(), current.column()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; # more than one row selected make the other 2 selections&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection = QItemSelection(self._start, current)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if current.row() < self._start.row():&nbsp; # stencil out diagonal&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; right = QItemSelection(current, self.index(self._start.row() - 1, 6))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left = QItemSelection(self.index(current.row() + 1, 0), self._start)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(right, QItemSelectionModel.Select)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(left, QItemSelectionModel.Select)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if current.column() > self._start.column():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stencil = QItemSelection(self.index(current.row(), current.column() - 1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.index(current.row(), 0))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stencil2 = QItemSelection(self.index(self._start.row(), self._start.column() + 1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.index(self._start.row(), 6))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(stencil, QItemSelectionModel.Deselect)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(stencil2, QItemSelectionModel.Deselect)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; right = QItemSelection(self._start, self.index(current.row() - 1, 6))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left = QItemSelection(self.index(self._start.row() + 1, 0), current)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(right, QItemSelectionModel.Select)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(left, QItemSelectionModel.Select)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if current.column() < self._start.column():&nbsp; # stencil out diagonal&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stencil = QItemSelection(self.index(self._start.row(), self._start.column() - 1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.index(self._start.row(), 0))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stencil2 = QItemSelection(self.index(current.row(), current.column() + 1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.index(current.row(), 6))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(stencil, QItemSelectionModel.Deselect)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selection.merge(stencil2, QItemSelectionModel.Deselect)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.selectionModel().select(selection, QItemSelectionModel.Select)if __name__ == '__main__':&nbsp; &nbsp; import sys&nbsp; &nbsp; from PyQt5.QtWidgets import QApplication, QTableView&nbsp; &nbsp; app = QApplication(sys.argv)&nbsp; &nbsp; model = TableModel()&nbsp; &nbsp; cal = CalendarView()&nbsp; &nbsp; cal.setModel(model)&nbsp; &nbsp; cal.show()&nbsp; &nbsp; cal.resize(860, 640)&nbsp; &nbsp; sys.exit(app.exec_())
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python