IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Glisser-déposer entre un QTreeWidget et un QTableWidget


Sujet :

PyQt Python

  1. #1
    Futur Membre du Club
    Inscrit en
    Novembre 2010
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Glisser-déposer entre un QTreeWidget et un QTableWidget
    Bonjour à tous,

    Je voudrais pouvoir passer le text d'un item de QTreeWidget à une cellule d'un QTableWidget. L'idéal serait de trouver position de la cellule sous la souris un peu comme ci c'était en mode InternalMove. Je n'y arrive pas du tout. Pourriez vous m'aider s'il vous plait.

    Romung

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    import sys
    from PyQt4 import QtCore, QtGui
     
    class QCustomTableWidget (QtGui.QTableWidget):
     
        def __init__ (self, parent = None):
     
            super(QCustomTableWidget, self).__init__(parent)
     
            self.setColumnCount(2)
            self.setRowCount(2)
            self.setItem(0, 0, QtGui.QTableWidgetItem('cell'))
     
            self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
     
        def dragEnterEvent (self, eventQDragEnterEvent):
     
            sourceQCustomTableWidget = eventQDragEnterEvent.source()
     
            if isinstance(sourceQCustomTableWidget, QtGui.QTreeWidget) and (self is not     sourceQCustomTableWidget):
                eventQDragEnterEvent.accept()
            else:
                QtGui.QTableWidget.dragEnterEvent(self, eventQDragEnterEvent)
     
        def dropEvent (self, eventQDropEvent):
     
            sourceQCustomTableWidget = eventQDropEvent.source()
     
            if isinstance(sourceQCustomTableWidget, QtGui.QTreeWidget) and (self is not sourceQCustomTableWidget):
                sourceQTableWidgetItem      = sourceQCustomTableWidget.currentIndex()
                destinationQTableWidgetItem = str(sourceQTableWidgetItem.data().toString())
     
               ##############################################################################
               ##############################################################################
               ##############################################################################
                self.setItem('???', '???', QtGui.QTableWidgetItem(destinationQTableWidgetItem))
               ##############################################################################
               ##############################################################################
               ##############################################################################
     
            else:
                QtGui.QTableWidget.dropEvent(self, eventQDropEvent)
     
    class QCustomQWidget (QtGui.QWidget):
     
        def __init__ (self, parent = None):
     
            super(QCustomQWidget, self).__init__(parent)
     
            self.my1QCustomTableWidget  = QCustomTableWidget(self)
     
            self.myQTreeWidget   = QtGui.QTreeWidget(self)
            self.myQTreeWidget.setDragEnabled(True)
            listsExampleQTreeWidgetItem = [QtGui.QTreeWidgetItem([name]) for name in ['A', 'B', 'C']]
            self.myQTreeWidget.addTopLevelItems(listsExampleQTreeWidgetItem)
     
            self.allQHBoxLayout = QtGui.QHBoxLayout()
            self.allQHBoxLayout.addWidget(self.my1QCustomTableWidget)
            self.allQHBoxLayout.addWidget(self.myQTreeWidget)
            self.setLayout(self.allQHBoxLayout)
     
    app = QtGui.QApplication(sys.argv)
    myQCustomQWidget = QCustomQWidget()
    myQCustomQWidget.show()
    sys.exit(app.exec_())

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 298
    Points : 6 778
    Points
    6 778
    Par défaut
    Salut,

    Tu réimplémentes les méthodes dragEnterEvent, dropEvent, tu voulais un drag&drop customisé ?

    Avec ce simple exemple, le drag&drop est fonctionnel. Dans les deux sens.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    # -*- coding: utf-8 -*-
     
    from PyQt4 import QtCore, QtGui
     
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.resize(640, 466)
            self.centralwidget = QtGui.QWidget(MainWindow)
            self.gridLayout = QtGui.QGridLayout(self.centralwidget)
            self.horizontalLayout = QtGui.QHBoxLayout()
            self.treeWidget = TreeWidget(self.centralwidget)
            self.treeWidget.setDragEnabled(True)
            self.treeWidget.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
            self.treeWidget.setDefaultDropAction(QtCore.Qt.CopyAction)
            self.treeWidget.setAlternatingRowColors(True)
            self.treeWidget.headerItem().setText(0, "1")
            self.horizontalLayout.addWidget(self.treeWidget)
            self.tableWidget = TableWidget(self.centralwidget)
            self.tableWidget.setDragEnabled(True)
            self.tableWidget.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
            self.tableWidget.setDefaultDropAction(QtCore.Qt.CopyAction)
            self.tableWidget.setColumnCount(2)
            self.tableWidget.setRowCount(0)
            self.tableWidget.horizontalHeader().setDefaultSectionSize(150)
            self.horizontalLayout.addWidget(self.tableWidget)
            self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
            MainWindow.setCentralWidget(self.centralwidget)
     
     
    class TreeWidget(QtGui.QTreeWidget):
        def __init__(self, parent=None):
            super(TreeWidget, self).__init__(parent)
            lst = [QtGui.QTreeWidgetItem([name]) for name in ['A', 'B', 'C']]
            self.addTopLevelItems(lst)
     
     
    class TableWidget(QtGui.QTableWidget):
        def __init__(self, parent=None):
            super(TableWidget, self).__init__(parent)
     
     
    if __name__ == "__main__":
        import sys
        app = QtGui.QApplication(sys.argv)
        MainWindow = QtGui.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())

  3. #3
    Futur Membre du Club
    Inscrit en
    Novembre 2010
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci pour ton aide,

    En fait j'ai mal choisi mon exemple simplifié. Dans mon application j'utilise un QTreeView avec un model pour afficher des répertoires et fichiers de mon disque local. Du coup, je crois qu'il faut que je ré implémente Drag and Drop pour juste récupérer le nom/text du répertoire et le déplacer dans une cellule du tableau. J'ai retouché ton programme en accord avec ce que je viens de raconter. Le drop ne m'est plus permis.

    Romain

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    # -*- coding: utf-8 -*-
     
    from PyQt4 import QtCore, QtGui
     
    class Ui_MainWindow(object):
     
        def setupUi(self, MainWindow):
     
            MainWindow.resize(640, 466)
            self.centralwidget = QtGui.QWidget(MainWindow)
            self.gridLayout = QtGui.QGridLayout(self.centralwidget)
            self.horizontalLayout = QtGui.QHBoxLayout()
            self.treeWidget = TreeWidget(self.centralwidget)        
            self.horizontalLayout.addWidget(self.treeWidget)
            self.tableWidget = TableWidget(self.centralwidget)
            self.horizontalLayout.addWidget(self.tableWidget)
            self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
            MainWindow.setCentralWidget(self.centralwidget)
     
     
    class TreeWidget(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(TreeWidget, self).__init__(parent)
     
            model = QtGui.QFileSystemModel()
            model.setRootPath(QtCore.QDir.currentPath())
            treeView = QtGui.QTreeView()
            treeView.setModel(model)
            treeView.setDragEnabled(True)
            treeView.setAlternatingRowColors(True)
            self.layout = QtGui.QVBoxLayout(self)
            self.layout.addWidget(treeView)
     
    class TableWidget(QtGui.QTableWidget):
        def __init__(self, parent=None):
            super(TableWidget, self).__init__(parent)
     
            self.setDragEnabled(True)
            self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
            self.setDefaultDropAction(QtCore.Qt.CopyAction) 
            self.setColumnCount(2)
            self.setRowCount(0) 
            self.horizontalHeader().setDefaultSectionSize(150)
     
    if __name__ == "__main__":
        import sys
        app = QtGui.QApplication(sys.argv)
     
        MainWindow = QtGui.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())

  4. #4
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 298
    Points : 6 778
    Points
    6 778
    Par défaut
    Je m'en doutais un peu, alors faut gérer le drag and drop.

    Un exemple simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
     
    # -*- coding: utf-8 -*-
     
    import os
    import sys
     
    from PyQt4 import QtCore, QtGui
     
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.resize(640, 466)
            self.centralwidget = QtGui.QWidget(MainWindow)
            self.gridLayout = QtGui.QGridLayout(self.centralwidget)
            self.horizontalLayout = QtGui.QHBoxLayout()
            self.treeView = TreeView(self, self.centralwidget)
            self.horizontalLayout.addWidget(self.treeView)
            self.tableWidget = TableWidget(self, self.centralwidget)
            self.horizontalLayout.addWidget(self.tableWidget)
            self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
            MainWindow.setCentralWidget(self.centralwidget)
     
            self.files_dragged = []
            self.treeView.set_source(os.path.expanduser('~'))
     
     
    class TreeView(QtGui.QTreeView):
        def __init__(self, main, parent=None):
            super(TreeView, self).__init__(parent)
            self.main = main
            self.setDragEnabled(True)
            self.setDragDropMode(QtGui.QAbstractItemView.DragOnly)
            self.setDefaultDropAction(QtCore.Qt.CopyAction)
            self.setAlternatingRowColors(True)
            self.setHeaderHidden(True)
            self.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
     
        def set_source(self, folder):
            folder = folder.rstrip(os.path.sep)
            self.top = folder
            self.root = os.path.dirname(folder)
            self.dirModel = QtGui.QFileSystemModel()
            self.dirModel.setRootPath(QtCore.QDir.homePath())
            self.setModel(self.dirModel)
            self.setRootIndex(self.dirModel.index(self.root)) 
            self.setWordWrap(True)
            self.hideColumn(1)
            self.hideColumn(2)
            self.hideColumn(3)
            idx = self.dirModel.index(folder)
            self.expand(idx)
     
        def startDrag(self, event):
            if not self.selectedIndexes():
                return
     
            paths = []
            for s in self.selectedIndexes():
                paths.append(unicode(self.dirModel.filePath(s)))
     
            self.main.files_dragged = paths
            mimeData = QtCore.QMimeData()
            mimeData.setText("files")
            drag = QtGui.QDrag(self)
            drag.setMimeData(mimeData)
            # Si l'on veut une icône ...
            #pixmap = QtGui.QPixmap("medias/file_ico.svg")
            #drag.setPixmap(pixmap)
            #drag.setHotSpot(QtCore.QPoint(pixmap.width()/2, pixmap.height()))
            #drag.setPixmap(pixmap)
            result = drag.start(QtCore.Qt.MoveAction)
            event.accept()
     
        def mouseMoveEvent(self, event):
            self.startDrag(event)
     
        def mousePressEvent(self, event):
            mod = QtGui.QApplication.keyboardModifiers()
            idx = self.indexAt(event.pos())
            btn = event.button()
            if btn == 1 and (not idx.isValid() or mod == QtCore.Qt.NoModifier):
                self.clearSelection()
            QtGui.QTreeView.mousePressEvent(self, event)
     
     
     
    class TableWidget(QtGui.QTableWidget):
        def __init__(self, main, parent=None):
            super(TableWidget, self).__init__(parent)
            self.main = main
            self.setDragDropMode(QtGui.QAbstractItemView.DropOnly)
            self.setDefaultDropAction(QtCore.Qt.CopyAction)
            self.setColumnCount(2)
            self.setRowCount(0)
            self.horizontalHeader().setDefaultSectionSize(150)
     
        def dragEnterEvent(self, event):
            if event.mimeData().hasText():
                print "has text"
                event.accept()
     
            else:
                print "ignore"
                event.ignore()
     
        def dragMoveEvent(self, event):
            if event.mimeData().hasText():
                event.setDropAction(QtCore.Qt.MoveAction)
                event.accept()
     
            else:
                event.ignore()
     
        def dropEvent(self, event):
            data = event.mimeData()
            print "data:", data.text()
            if data.text() == "files":
                self.add_files()
     
            event.accept()
     
        def add_files(self):
            for f in self.main.files_dragged:
                r = self.rowCount()
                self.insertRow(r)
                item = QtGui.QTableWidgetItem(f)
                self.setItem(r, 0, item)
     
            self.main.files_dragged = []
     
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        MainWindow = QtGui.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())

  5. #5
    Futur Membre du Club
    Inscrit en
    Novembre 2010
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci pour l'exemple et j'y vois un peu plus claire. Mais par contre j'ai toujours le même problème qui revient. Quand je drag l'item au dessus du QTableWidget, je n'arrive pas à le déposer dans une cellule située sous la souris (en considérant un tableau 5*5 prédéfini par exemple). Sur quoi appliquer .row() et .colomn()? Peut être avec enterEvent?

    romain

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        def add_files(self):
     
            for f in self.main.files_dragged:
    #            r = self.rowCount()
    #            self.insertRow(r)
                item = QtGui.QTableWidgetItem(f)
                self.setItem(????, ????, item)
     
            self.main.files_dragged = []

  6. #6
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 298
    Points : 6 778
    Points
    6 778
    Par défaut
    Cette fois ci je vais te laisser te débrouiller mais en te donnant quelques pistes malgré tout.

    La méthode dropEvent est réimplémentée du QTableWidget, or les event sont en général des classes.

    Nous allons voir dans la doc[0] et il existe effectivement une classe QDropEvent[1] où l'on découvre que cet event possède une méthode pos() qui retourne un QPoint.

    Retour dans la doc du QTableWidget[2] où nous trouvons une méthode itemAt(QPoint) qui retourne l'item recherché.

    Je pense que tu vas t'en sortir avec ça.


    [0] http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
    [1] http://pyqt.sourceforge.net/Docs/PyQt4/qdropevent.html
    [2] http://pyqt.sourceforge.net/Docs/PyQ...blewidget.html

  7. #7
    Futur Membre du Club
    Inscrit en
    Novembre 2010
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Je te remercie!

    Romain

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de glisser-déposer sur un QTreeWidget
    Par JakRenegade dans le forum Débuter
    Réponses: 1
    Dernier message: 25/05/2014, 18h17
  2. Glisser-déposer entre QWidget différents
    Par EvaBraun dans le forum Débuter
    Réponses: 1
    Dernier message: 24/11/2012, 11h59
  3. Glisser-déposer entre deux QTreeView
    Par sfarc dans le forum Débuter
    Réponses: 21
    Dernier message: 16/05/2012, 11h59
  4. Glisser-déposer entre deux zones de listes
    Par Arkham46 dans le forum Contribuez
    Réponses: 2
    Dernier message: 13/04/2012, 13h20
  5. Glisser-déposer entre ListView
    Par Troudhyl dans le forum Qt Quick
    Réponses: 5
    Dernier message: 18/01/2012, 14h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo