J'ai une application Qt4 (à l'aide des liaisons PYQT) qui contient un Je peux ajouter des éléments, et ceci Permet de faire glisser et déposer pour réorganiser la liste. Mais comment puis-je obtenir une notification lorsque la liste est réorganisée par l'utilisateur? J'ai essayé d'ajouter un qlistwidget code>, initialisé comme:
dropmimedata (auto, index, données, action) code> méthode à la classe, mais elle n'est jamais appelée. P> P>
6 Réponses :
Pas une solution, mais quelques idées: p>
Vous devriez probablement vérifier ce qui est renvoyé par la méthode supportée en prenant en charge. Il se peut que vous ayez besoin de remplacer cette méthode, d'inclure QT :: MOVEaction ou QT :: Copyaction. P>
Vous avez le signal QListView :: indexesMoved, mais je ne suis pas sûr que cela soit émis si vous utilisez qlistwidget. Ça vaut la peine de vérifier. P>
Il existe un bogue connu dans Qt 4.5.x que le signal QListView :: indexesMoved ne tire jamais. Vous êtes obligé d'installer un evirfilter et de le gérer vous-même.
Je viens de faire face à cela et que c'est une douleur dans le cul, mais voici quoi faire:
Vous devez installer un J'écris mon QT en C ++, mais voici une version Pythonification: P> EventFilter code> sur votre
listwidget code> Sous-classe et ensuite surveiller le
événement code> enfant. Cet événement couvre des mouvements ainsi que la suppression, il devrait donc fonctionner pour réorganiser des éléments avec glisser-déposer dans une liste. P>
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
self.setDragDropMode(self.InternalMove)
self.installEventFilter(self)
def eventFilter(self, sender, event):
if (event.type() == QEvent.ChildRemoved):
self.on_order_changed()
return False # don't actually interrupt anything
def on_order_changed(self):
# do magic things with our new-found knowledge
Merci pour cela, j'ai mis en place le code dans Pyside et travaille bien.
Je sais que c'est vieux, mais j'ai pu obtenir mon code pour travailler à l'aide de la réponse de Trey et je voulais partager ma solution Python. Ceci est pour un qlistwidget code> à l'intérieur d'un
qdialog code>, pas celui qui est sous-classé.
class NotesDialog(QtGui.QDialog):
def __init__(self, notes_list, notes_dir):
QtGui.QDialog.__init__(self)
self.ui=Ui_NotesDialog()
# the notesList QListWidget is created here (from Qt Designer)
self.ui.setupUi(self)
# install an event filter to catch internal QListWidget drop events
self.ui.notesList.installEventFilter(self)
def eventFilter(self, sender, event):
# this is the function that processes internal drop in notesList
if event.type() == QtCore.QEvent.ChildRemoved:
self.update_views() # do something
return False # don't actually interrupt anything
J'ai un moyen plus facile. :) p>
Vous pouvez réellement accéder au modèle interne de ListWidget avec Si vous ne vous souciez que de glisser-déposer, connectez-vous à Si vous voulez savoir ce que proposé, myList-> modèle () code> - et de là, il y a beaucoup de signaux disponibles. P>
layoutChanged code>.
Si vous avez des boutons de déplacement (qui sont généralement implémentés avec Supprimer + Add), connectez-vous à
RowinsERTED code> aussi. P>
rowsmoved code> peut être meilleur que
layoutchanged code>. p>
Bienvenue sur Stackoverflow. Veuillez prendre quelques minutes pour savoir comment utiliser Mise en forme . Cela vous permettra de formater le code de code dans votre réponse et de rendre plus lisible pour tous les autres.
Les rowsmoved () ne peuvent pas émettre le signal ... J'ai testé ici, il ne saisit jamais la fente lorsque je déplace l'élément par glisser / goutte. mais article obtenez le changement de changement
Notez que le signal code> code> de cette réponse vous indique quels éléments ont été déplacés et où, tandis que le qevent.childremoved code> EventFilter dans la réponse acceptée ne le fait pas.
J'ai trouvé La réponse de Trey STOUT a fonctionné cependant que j'avais évidemment des événements lorsque la commande de liste n'avait pas réellement changé. Je me suis tourné vers La réponse de Chani qui fonctionne comme requise mais sans code, il m'a fallu un peu de travail pour mettre en œuvre dans Python. < P> Je pensais que je partagerais l'extrait de code pour aider les futurs visiteurs: p> ceci est testé en pyside mais ne vois aucune raison pour laquelle il ne fonctionnerait pas dans Pyqt. p> p>
J'ai testé cela dans Pyqt5, et sauf si je fais quelque chose de mal, cette approche ne fonctionne pas, voir la réponse ci-dessous
Le qlistwidget.model () code> L'approche semblait le plus élégant des solutions proposées mais ne fonctionnait pas pour moi dans PYQT5. Je ne sais pas pourquoi, mais peut-être que quelque chose a changé en mouvement vers Qt5. L'approche
EventFilter CODE> fonctionnait, mais une autre alternative mérite d'être envisagée: surmonter le QDropEvent et la vérification si l'événement est-il. Voir le code ci-dessous qui est un MVCE avec toutes les solutions proposées codées pour vérifier dans PYQT5:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
class MyList(QtWidgets.QListWidget):
itemMoved = QtCore.pyqtSignal()
def __init__(self):
super(MyList, self).__init__()
self.setDragDropMode(self.InternalMove)
list_model = self.model()
# list_model.layoutChanged.connect(self.onLayoutChanged) # doesn't work
# self.installEventFilter(self) # works
self.itemMoved.connect(self.onLayoutChanged) # works
def onLayoutChanged(self):
print("Layout Changed")
def eventFilter(self, sender, event):
"""
Parameters
----------
sender : object
event : QtCore.QEvent
"""
if event.type() == QtCore.QEvent.ChildRemoved:
self.onLayoutChanged()
return False
def dropEvent(self, QDropEvent):
"""
Parameters
----------
QDropEvent : QtGui.QDropEvent
"""
mime = QDropEvent.mimeData() # type: QtCore.QMimeData
source = QDropEvent.source()
if source is self:
super(MyList, self).dropEvent(QDropEvent)
self.itemMoved.emit()
app = QtWidgets.QApplication([])
form = MyList()
for text in ("one", "two", "three"):
item = QtWidgets.QListWidgetItem(text)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
item.setCheckState(QtCore.Qt.Checked)
form.addItem(item)
form.show()
sys.exit(app.exec_())
La réponse de @chani (pas la réponse actuellement acceptée) est la solution la plus facile à cela.
Possible, je fais quelque chose de mais la réponse de @chani n'a pas fonctionné dans mon exemple pour PyqT5. La réponse acceptée a fonctionné de même que QdroPevent comme dans ma réponse ci-dessous