【问题标题】:Integrating Calendar Widget into QTableView将日历小部件集成到 QTableView
【发布时间】:2021-07-06 15:24:51
【问题描述】:

当我在表格视图中选择日期列时,我试图打开一个日历小部件。我设法做到了这一点,但是当单元格的编辑完成时(用户单击单元格),单元格显示 PyQt5.QtCore.QDate(2021, 1, 1) 21 年 1 月 1 日

日期代表:

class DateDelegate(QtWidgets.QStyledItemDelegate): # calender widget
    def __init__(self, owner):
        super().__init__(owner)
        self.table = owner.model()
    def createEditor(self, parent, option, index):
        widget = QtWidgets.QDateEdit(parent)         
        widget.setCalendarPopup(True) 
        widget.setDate(datetime.datetime.strptime(self.table.data(index), "%d-%b-%y"))
        return widget

主窗口:

self.view = QtWidgets.QTableView(self)
self.model = PandasModel(self.dataframe)
self.view.setModel(self.model)
self.view.setItemDelegateForColumn(13,DateDelegate(self.view))

熊猫模型:

class PandasModel(QtCore.QAbstractTableModel):
    """
    Class to populate a table view with a pandas dataframe
    """
    def __init__(self, data, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self._data = np.array(data.values)
        self._cols = data.columns
        self.r, self.c = np.shape(self._data)

    def rowCount(self, index):
        return self.r

    def columnCount(self, index):
        return self.c

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole or role == Qt.EditRole:
                value = self._data[index.row()][index.column()] 
                if isinstance(value, NaTType): # NaTType given to Date strings that can't be converted to pandas Timestamp
                    return ""
                if isinstance(value, datetime.date):
                    return value.strftime("%d-%b-%y")
                if isinstance(value, float):
                    return int(value)
                
                return str(value)

            if role == Qt.BackgroundRole:
                if self._data[index.row()][18].upper() == "PASS":       # Highlight passes as green
                    green = QtGui.QColor(43,235,101)
                    return QtGui.QBrush(green)
                elif self._data[index.row()][18].upper() == "FAIL":     # Failures
                    red = QtGui.QColor(255,75,75)
                    return QtGui.QBrush(red)
                elif self._data[index.row()][18].upper() == "F.E.A.":
                    cyan = QtGui.QColor(40,208,191)
                    return QtGui.QBrush(cyan)
                elif self._data[index.row()][24]:               # Cancelled
                    return QtGui.QBrush(Qt.lightGray)
                elif not isinstance(self._data[index.row()][30], NaTType):
                    if self._data[index.row()][16] > datetime.datetime.today():    # Late to Finish (Planned Finish)
                        darkPink = QtGui.QColor(225,40,126)
                        return QtGui.QBrush(darkPink)
                elif not isinstance(self._data[index.row()][15], NaTType):
                    if self._data[index.row()][15] < datetime.datetime.today():    # In progress (DateStarted)
                        orange = QtGui.QColor(255,211,63)
                        return QtGui.QBrush(orange)     
                elif not isinstance(self._data[index.row()][29], NaTType):
                    if self._data[index.row()][29] > datetime.datetime.today():    # Late to Start (Planned Start)
                        pink = QtGui.QColor(255,163,175)
                        return QtGui.QBrush(pink)                      
        else:
            return False       
        
    def setData(self, index, value, role):
        if role == Qt.EditRole:
            self._data[index.row()][index.column()] = value
            #print(value)
            return True
        
    def flags(self, index):
        return Qt.ItemIsSelectable|Qt.ItemIsEnabled|Qt.ItemIsEditable

    def headerData(self, p_int, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self._cols[p_int]
            elif orientation == QtCore.Qt.Vertical:
                return p_int
        return None

【问题讨论】:

    标签: python date user-interface pyqt5


    【解决方案1】:

    问题是您假设 QDate 到字符串或日期时间的转换是隐式的,但事实并非如此,因此您必须重写 setEditorData 和 setModelData 方法:

    from datetime import datetime
    
    from PyQt5 import QtCore, QtWidgets
    
    DATE_FORMAT = "%d-%b-%y"
    
    
    class DateDelegate(QtWidgets.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            widget = QtWidgets.QDateEdit(parent)
            widget.setCalendarPopup(True)
            return widget
    
        def setEditorData(self, editor, index):
            if isinstance(editor, QtWidgets.QDateEdit):
                dt_str = index.data(QtCore.Qt.EditRole)
                dt = datetime.strptime(dt_str, DATE_FORMAT)
                editor.setDate(dt)
                return
            super().setEditorData(editor, index)
    
        def setModelData(self, editor, model, index):
            if isinstance(editor, QtWidgets.QDateEdit):
                dt = editor.date().toPyDate()
                model.setData(index, dt, QtCore.Qt.EditRole)
                return
            super().setModelData(editor, model, index)
    

    【讨论】:

    • 完美!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    相关资源
    最近更新 更多