微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PyQt5:QTableView 拖放单元格而不是行

如何解决PyQt5:QTableView 拖放单元格而不是行

我知道如何drag rows

    QTableView.verticalHeader().setSectionsMovable(True)
    QTableView.verticalHeader().setDragEnabled(True)
    QTableView.verticalHeader().setDragDropMode(qtw.QAbstractItemView.InternalMove)

但我希望能够拖放一个(或一对)单元格。

谁能指出我正确的方向?

PS:我目前的想法是拦截 clicked() -> dragenter() -> dragLeave() 或 fork 到 dragDrop() -> dragIndicatorPosition() 事件,但听起来有点复杂

我确实阅读了 this,但我对如何实现它感到困惑,尤其是“启用项目拖放”部分似乎正是我所需要的。我会看看我是否可以发布一个“苗条”的例子。

编辑:

这里有一些其他东西的例子。在 MyStandardItemmodel 中,我尝试做到这一点:

from PyQt5 import QtCore,QtWidgets,Qtsql
from PyQt5.QtCore import QModelIndex
from PyQt5.QtGui import QStandardItemmodel
from PyQt5.QtWidgets import QApplication,QTableView,QTableWidget


class MyStandardItemmodel(QStandardItemmodel):
    def __init__(self,parent=None,*arg,**kwargs):
        super().__init__(parent,**kwargs)
        self.__readonly_cols = []

    def flags(self,index: QtCore.QModelIndex) -> QtCore.Qt.ItemFlags:
        try:
            default_Flags = QStandardItemmodel.flags(self,index)
            if (index.column() in self.__readonly_cols):
                return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
            else:
                if (index.isValid()):
                    return default_Flags | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
                else:
                    return default_Flags
        except Exception as ex:
            print(ex)


    def setReadOnly(self,columns: [int]):
        for i in columns:
            if i <= (self.columnCount() - 1) and i not in self.__readonly_cols:
                self.__readonly_cols.append(i)

    def resetReadOnly(self):
        self.__readonly_cols = []


class MyTableView(QtWidgets.QTableView):
    def __init__(self,*args,**kwargs)



class CheckBoxDelegate(QtWidgets.QItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox cell of the column to which it's applied.
    """
    # signal to inform clicking
    user_click = QtCore.pyqtSignal(int,int,bool)

    def __init__(self,parent):
        QtWidgets.QItemDelegate.__init__(self,parent)

    def createEditor(self,parent,option,index):
        """
        Important,otherwise an editor is created if the user clicks in this cell.
        """
        return None

    def paint(self,painter,index):
        """
        Paint a checkBox without the label.
        """
        self.drawCheck(painter,option.rect,QtCore.Qt.Unchecked if int(index.data()) == 0 else QtCore.Qt.Checked)

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

        if event.type() == QtCore.QEvent.MouseButtonRelease and event.button() == QtCore.Qt.LeftButton:
            # Change the checkBox-state
            self.setModelData(None,index)
            return True

        # if event.type() == QtCore.QEvent.MouseButtonPress or event.type() == QtCore.QEvent.MouseMove:
        #     return False

        return False


    def setModelData (self,editor,index):
        '''
        The user wanted to change the old state in the opposite.
        '''
        try:
            if int(index.data()) == 0:
                model.setData(index,1,QtCore.Qt.EditRole)
                ret = True
            else:
                model.setData(index,QtCore.Qt.EditRole)
                ret = False
            # emit signal with row,col,and the status
            self.user_click.emit(index.row(),index.column(),ret)
        except Exception as ex:
            print(ex)


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)
    model = MyStandardItemmodel(5,5)
    header_labels = ['','Signal','Type','Routing','Input']
    model.setHorizontalHeaderLabels(header_labels)
    tableView = MyTableView()
    tableView.setModel(model)

    delegate = CheckBoxDelegate(None)
    tableView.setItemDelegateForColumn(0,delegate)
    for row in range(5):
        for column in range(4):
            index = model.index(row,column,QModelIndex())
            model.setData(index,0)
    model.setReadOnly([1,2])
    tableView.setwindowTitle("CheckBox,readonly and drag&drop example")
    tableView.show()
    sys.exit(app.exec_())

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。