Вот полный рабочий пример:
from PyQt4 import QtCore, QtGui, Qt
import cPickle
import pickle
Почему вы используете cPickle
, а также pickle
?
class DragTable(QtGui.QTableView):
def __init__(self, parent = None):
super(DragTable, self).__init__(parent)
self.setDragEnabled(True)
self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
Вы, вероятно, хотите установить здесь поведение выборапотому что я предполагаю представление данных на основе строк.Конечно, вы можете изменить это.
def dragEnterEvent(self, event):
if event.mimeData().hasFormat("application/pubmedrecord"):
event.setDropAction(Qt.MoveAction)
event.accept()
else:
event.ignore()
def startDrag(self, event):
Ваш код предполагает здесь только один индекс, основанный на позиции события.Для QTableView
это не нужно, поскольку оно уже обрабатывает щелчок мыши.Вместо этого лучше полагаться на то, что Qt предоставит вам информацию, которая вам действительно нужна , как всегда.Здесь я решил использовать selectedIndexes()
.
indices = self.selectedIndexes()
Индексы - это теперь список QModelIndex
экземпляров, которые я решил преобразовать в набор номеров строк.Также возможно преобразовать их в список QPersistentModelIndex
es, в зависимости от ваших потребностей.
Здесь вас может удивить то, что индексы содержат индексы для всех ячеек втаблица, не все строки, независимо от поведения выбора.Вот почему я решил использовать set
вместо list
.
selected = set()
for index in indices:
selected.add(index.row())
Я оставил остальное нетронутым, предполагая, что вы знаете, что вы там делаете.
bstream = cPickle.dumps(selected)
mimeData = QtCore.QMimeData()
mimeData.setData("application/pubmedrecord", bstream)
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
pixmap = QtGui.QPixmap(":/drag.png")
drag.setHotSpot(QtCore.QPoint(pixmap.width()/3, pixmap.height()/3))
drag.setPixmap(pixmap)
result = drag.start(QtCore.Qt.MoveAction)
def mouseMoveEvent(self, event):
self.startDrag(event)
class TagLabel(QtGui.QLabel):
def __init__(self, text, color, parent = None):
super(TagLabel, self).__init__(parent)
self.tagColor = color
self.setText(text)
self.setStyleSheet("QLabel { background-color: %s; font-size: 14pt; }" % self.tagColor)
self.defaultStyle = self.styleSheet()
self.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasFormat("application/pubmedrecord"):
self.set_bg(True)
event.accept()
else:
event.reject()
def dragLeaveEvent(self, event):
self.set_bg(False)
event.accept()
def dropEvent(self, event):
self.set_bg(False)
data = event.mimeData()
bstream = data.retrieveData("application/pubmedrecord", QtCore.QVariant.ByteArray)
selected = pickle.loads(bstream.toByteArray())
event.accept()
self.emit(QtCore.SIGNAL("dropAccepted(PyQt_PyObject)"), (selected, str(self.text()), str(self.tagColor)))
Если вы не взаимодействуете с C ++ - код с этим сигналом, здесь нет необходимости добавлять аргумент сигнала, вы также можете использовать dropAccepted
без скобок, и PyQt4 будет делать правильные вещи.
def set_bg(self, active = False):
if active:
style = "QLabel {background: yellow; font-size: 14pt;}"
self.setStyleSheet(style)
else:
self.setStyleSheet(self.defaultStyle)
app = QtGui.QApplication([])
l = TagLabel("bla bla bla bla bla bla bla", "red")
l.show()
m = QtGui.QStandardItemModel()
for _ in xrange(4):
m.appendRow([QtGui.QStandardItem(x) for x in ["aap", "noot", "mies"]])
t = DragTable()
t.setModel(m)
t.show()
def h(o):
print "signal handled", o
l.connect(l, QtCore.SIGNAL("dropAccepted(PyQt_PyObject)"), h)
app.exec_()