【问题标题】:Pyside - delegate readonly checkboxPyside - 委托只读复选框
【发布时间】:2014-10-10 19:07:29
【问题描述】:

我想将 readonly 复选框委托给 QTableWidget

我有以下类用于显示已启用(可编辑)的复选框

from PySide import QtCore, QtGui

class CheckBoxDelegate(QtGui.QStyledItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox in every
    cell of the column to which it's applied
    """
    def __init__(self, parent):
        QtGui.QStyledItemDelegate.__init__(self, parent)
        self.parent = parent

    def createEditor(self, parent, option, index):
        '''
        Important, otherwise an editor is created if the user clicks in this cell.
        ** Need to hook up a signal to the model
        '''
        return None

    def paint(self, painter, option, index):
        '''
        Paint a checkbox without the label.
        '''

        checked = index.data() #.toBool()
        check_box_style_option = QtGui.QStyleOptionButton()

        if (index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            check_box_style_option.state |= QtGui.QStyle.State_Enabled
        else:
            check_box_style_option.state |= QtGui.QStyle.State_ReadOnly

        if checked:
            check_box_style_option.state |= QtGui.QStyle.State_On
        else:
            check_box_style_option.state |= QtGui.QStyle.State_Off

        check_box_style_option.rect = self.getCheckBoxRect(option)

        #if not index.model().hasFlag(index, Qt.ItemIsEditable):
        #check_box_style_option.state |= QtGui.#QStyle.State_ReadOnly

        check_box_style_option.state |= QtGui.QStyle.State_Enabled

        QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_CheckBox, check_box_style_option, painter)

    def editorEvent(self, event, model, option, index):
        '''
        Change the data in the model and the state of the checkbox
        if the user presses the left mousebutton or presses
        Key_Space or Key_Select and this cell is editable. Otherwise do nothing.
        '''
        if not (index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            return False

        # Do not change the checkbox-state
        if event.type() == QtCore.QEvent.MouseButtonPress:
          return False
        if event.type() == QtCore.QEvent.MouseButtonRelease or event.type() == QtCore.QEvent.MouseButtonDblClick:
            if event.button() != QtCore.Qt.LeftButton or not self.getCheckBoxRect(option).contains(event.pos()):
                return False
            if event.type() == QtCore.QEvent.MouseButtonDblClick:
                return True
        elif event.type() == QtCore.QEvent.KeyPress:
            if event.key() != QtCore.Qt.Key_Space and event.key() != QtCore.Qt.Key_Select:
                return False
            else:
                return False

        # Change the checkbox-state
        self.setModelData(None, model, index)
        return True

    def setModelData (self, editor, model, index):
        '''
        The user wanted to change the old state in the opposite.
        '''
        newValue = QtCore.Qt.Checked if not index.data() else QtCore.Qt.Unchecked
        model.setData(index, newValue, QtCore.Qt.EditRole)

    def getCheckBoxRect(self, option):
        check_box_style_option = QtGui.QStyleOptionButton()
        check_box_rect = QtGui.QApplication.style().subElementRect(QtGui.QStyle.SE_CheckBoxIndicator, check_box_style_option, None)
        check_box_point = QtCore.QPoint (option.rect.x() +
                            option.rect.width() / 2 -
                            check_box_rect.width() / 2,
                            option.rect.y() +
                            option.rect.height() / 2 -
                            check_box_rect.height() / 2)
        return QtCore.QRect(check_box_point, check_box_rect.size())

我还想添加另外两个功能

def setEnabled(editor)
def setDiabled(editor)

关键是我想将一些复选框设置为只读,并在选中另一个复选框时启用它们(这还不重要,我首先想创建一个只读复选框,其余的我会自己做)

-- 编辑--

我想到了以下解决方案

每次添加新行时首先禁用该项目

def addRow(self):
        ...
        ...
        self.item(row+1, 3).setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

在另一个函数中

def activate(self):
    self.blockSignals(True)
    ...
    ...
    user_readable = self.item(row, 2).data(QtCore.Qt.DisplayRole)
        if user_readable == QtCore.Qt.Checked:
            print user_readable
            print self.item(row, 3).flags()
            self.item(row, 3).setFlags(self.item(row, 3).flags() & QtCore.Qt.ItemIsEnabled)
        else:
            self.item(row, 3).setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

【问题讨论】:

    标签: python qt5 pyside qitemdelegate qcheckbox


    【解决方案1】:

    如果我理解正确,这是一个简单的解决方案,我认为它可以满足您的需求。

    class ReadOnlyCheck(QtGui.QCheckBox):
        def __init__(self, parent=None, *args):
            QtGui.QCheckBox.__init__(self, parent, *args)
    
        def mousePressEvent(self, event):
            event.ignore()
    

    要使该框显示为选中状态,您可以使用setChecked(True),这样您就可以连接到来自其他复选框的信号,当它发生变化时。

    您可以使用setCellWidget 将这些输入到表格中。

    【讨论】:

    • 在事件中,您可以添加修饰符来调用通常的QtGui.QCheckBox.mousePressEvent,以防您希望通过点击。
    • 我想我可能会使用 setFlags 使 QTableWidgetitem 不可编辑,然后在选中另一个复选框时重新启用它。但我现在面临一个问题,如何在禁用它后重新启用它!见编辑
    • 我看不到你在哪里设置了标志,只有你在哪里更改了显示样式。这不行吗?你会尝试我的(显然)简单的解决方案,还是坚持使用委托路线?
    • 这有点复杂 - 我建议您检查这些标志集是否会产生您所追求的行为,然后是否在正确的时间调用了应该设置它们的代码。跨度>
    猜你喜欢
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2015-11-28
    • 2013-11-23
    • 2023-02-06
    • 2013-10-25
    相关资源
    最近更新 更多