如何在QTreeWidget中拖动时释放之前隐藏屏幕截图?

时间:2014-08-21 15:20:47

标签: python drag-and-drop delegates pyqt qtreewidget

我想隐藏“拖动指示器”(拖动的行屏幕截图)仅在QTreeWidget中拖动时显示鼠标箭头,是否可能?

我试图重新实现mouseMoveEvent,“拖动指示器”消失但同时,拖放被禁用,我缺少什么

代码:

#!/usr/bin/env python2
import os
import sys
import re

from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, QString


class MyTreeWidget(QtGui.QTreeWidget):

    def mouseMoveEvent_xxx(self, e):
        mimeData = QtCore.QMimeData()
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        # pixmap = QtGui.QPixmap()
        # drag.setPixmap(pixmap)

        # drag.setHotSpot(e.pos())

        # QtGui.QTreeWidget.mouseMoveEvent(self,e)
        drag.exec_(QtCore.Qt.MoveAction)


    def dropEvent(self,e):
        QtGui.QTreeWidget.dropEvent(self,e)
        self.expandAll()
        e.accept()



class TheUI(QtGui.QDialog):

    def __init__(self, args=None, parent=None):
        super(TheUI, self).__init__(parent)
        self.layout = QtGui.QVBoxLayout(self)
        treeWidget = MyTreeWidget()

        button = QtGui.QPushButton('Add')
        self.layout.addWidget(treeWidget)
        self.layout.addWidget(button)
        treeWidget.setHeaderHidden(True)

        self.treeWidget = treeWidget
        self.button = button
        self.button.clicked.connect(lambda *x: self.addCmd())

        HEADERS = ( "script", "chunksize", "mem" )
        self.treeWidget.setHeaderLabels(HEADERS)
        self.treeWidget.setColumnCount( len(HEADERS) )

        self.treeWidget.setColumnWidth(0,160)
        self.treeWidget.header().show()

        self.treeWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)

        self.resize(500,500)
        for i in xrange(6):
            item =self.addCmd(i)
            if i in (3,4):
                self.addCmd('%s-1' % i,parent=item)

        self.treeWidget.expandAll()
        self.setStyleSheet("QTreeWidget::item{ height: 30px;  }")

    def addCmd(self, i,parent=None):
        'add a level to tree widget'

        root = self.treeWidget.invisibleRootItem()
        if not parent:
            parent=root
        item = QtGui.QTreeWidgetItem(parent,['script %s' %i,'1','150'])
        return item

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    gui = TheUI()
    gui.show()
    app.exec_()

截图:

enter image description here

我想隐藏蓝色拖动栏,同时保持鼠标箭头。(或者给它一些自定义像素图,或者更好地在拖动栏周围绘制虚线轮廓),这个想法不想掩盖其背后的树形内容,(在我的系统comopositing manager中被禁用,所以半透明是不可能的)

如果你将mouseMoveEvent_xxx重命名为mouseMoveEvent,你会看到我的意思,拖动被禁用,虽然我已经将dragDropMode设置为InternalMove

1 个答案:

答案 0 :(得分:2)

非常有趣!

我在Qt 4(C ++)中找到了拖动指示器的行为。最后,我发现方法void QAbstractItemView::startDrag(Qt::DropActions supportedActions)是控制开始拖动和拖动指示器。在Line 3217 - 3238可以告诉拖动的行为和线3229是你想要的(设置新图像或不设置它)。好的,解决方案是找到任何方法将该行3229放出或替换新的图像。当然,我们必须覆盖这种方法。但是,新的问题是C ++和你在python中的使用。我们必须改变一些东西,把它放在python中才能做好工作。 (铁杆......)

好的,就是这样。覆盖方法QAbstractItemView.startDrag (self, Qt.DropActions supportedActions);

来自C ++的

;

    .
    .
    .
void QAbstractItemView::startDrag(Qt::DropActions supportedActions)
{
Q_D(QAbstractItemView);
QModelIndexList indexes = d->selectedDraggableIndexes();
if (indexes.count() > 0) {
    QMimeData *data = d->model->mimeData(indexes);
    if (!data)
        return;
    QRect rect;
    QPixmap pixmap = d->renderToPixmap(indexes, &rect);
    rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
    QDrag *drag = new QDrag(this);
    drag->setPixmap(pixmap);
    drag->setMimeData(data);
    drag->setHotSpot(d->pressedPosition - rect.topLeft());
    Qt::DropAction defaultDropAction = Qt::IgnoreAction;
    if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
        defaultDropAction = Qt::CopyAction;
    if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
        d->clearOrRemove();
    }
}
    .
    .
    .

to python;

class QCustomTreeWidget (QtGui.QTreeWidget):
    .
    .
    .
    def startDrag (self, supportedActions):
        listsQModelIndex = self.selectedIndexes()
        if listsQModelIndex:
            dataQMimeData = self.model().mimeData(listsQModelIndex)
            if not dataQMimeData:
                return None
            dragQDrag = QtGui.QDrag(self)
            # dragQDrag.setPixmap(QtGui.QPixmap('test.jpg')) # <- For put your custom image here
            dragQDrag.setMimeData(dataQMimeData)
            defaultDropAction = QtCore.Qt.IgnoreAction
            if ((supportedActions & QtCore.Qt.CopyAction) and (self.dragDropMode() != QtGui.QAbstractItemView.InternalMove)):
                defaultDropAction = QtCore.Qt.CopyAction;
            dragQDrag.exec_(supportedActions, defaultDropAction)

实验结果

我测试了这段代码并实现了代码,工作正常。但是,在拖动指示器期间我无法捕捉图片。 (我使用Windows 7)


有用的参考:QDrag Class ReferenceQAbstractItemView