Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PyQt5 - incorrect behavior of treeview when dragging and dropping
QtWS25 Last Chance

PyQt5 - incorrect behavior of treeview when dragging and dropping

Scheduled Pinned Locked Moved Solved Qt for Python
9 Posts 2 Posters 1.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    VirtualFloat
    wrote on last edited by
    #1

    I have a a treeview with three items

    • item1
      • item2
    • item3

    If I pick up item3 and try to drag it onto item1 or item2 then nothing happens.
    Until I drag item3 OUTSIDE the window and then back in. Then all of a sudden everything works as it should.

    No idea if I'm doing something wrong or that this is a Qt bug.

    The following python code should reproduce the issue. Running Windows10 with Python 3.7.1 and Qt 5.7.9

    from PyQt5.QtCore import QMimeData
    from PyQt5.QtGui import QStandardItemModel, QStandardItem
    from PyQt5 import QtCore, QtWidgets
    
    
    
    class SceneTreeModel(QStandardItemModel):
    
        def mimeData(self, indexes):
    
            name = indexes[0].data()
            print('called mimeData on ' + name)
            mimedata = QMimeData()
            mimedata.setText(name)
            return mimedata
    
        def supportedDropActions(self):
            return QtCore.Qt.MoveAction
    
        def canDropMimeData(self, data, action, row, column, parent):
            print('can drop called on')
            print(parent.data())
            return True
    
        def dropMimeData(self, data, action, row, column, parent):
            parent_name = parent.data()
            node_name = data.text()
            print("Dropped {} onto {}".format(node_name, parent_name))
            return True
    
    def give_model():
        model = SceneTreeModel()
        # create a tree item
        item1 = QStandardItem('item1')
        item2 = QStandardItem('item2')
        item3 = QStandardItem('item3')
    
        model.invisibleRootItem().appendRow(item1)
        item1.appendRow(item2)
        model.invisibleRootItem().appendRow(item3)
    
        return model
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(200, 400)
            MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
    
            self.treeView = QtWidgets.QTreeView(MainWindow)
            self.treeView.setRootIsDecorated(False)
            self.treeView.setObjectName("treeView")
            self.treeView.header().setVisible(False)
    
            MainWindow.setCentralWidget(self.treeView)
    
            self.treeView.setModel(give_model())
            self.treeView.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
            self.treeView.expandAll()
    
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        MainWindow = QtWidgets.QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())
    
    1 Reply Last reply
    0
    • DenniD Offline
      DenniD Offline
      Denni
      wrote on last edited by Denni
      #2

      First while this might not have any effect on what you are doing you should do one or the other and the more standardish version would be the following if importing everything:

      import sys
      
      from PyQt5.QtCore import * 
      from PyQt5.QtGui import * 
      from PyQt5.QtWidgets import * 
      

      Also keep all your imports gathered together at the top makes it a lot easier to know what you are including that way.

      Or if importing specifically (always the better route unless you are importing a lot of things. Note you could just leave it exit and argv but I find this helps with knowing where it came from without importing that entire library. On the flip-side you really do not need sysArgv since you do not use it as such I would just replace that call with >> app = QApplication([]) Aka K.I.S.S. it (Keep It Simple but Smart) never add anything to your code you do not need and definitely if you are not going to use it.

      from sys import sysExit
      from sys import sysArgv
      
      from PyQt5.QtCore import QMimeData
      from PyQt5.QtGui import QStandardItemModel, QStandardItem 
      from PyQt5.QtWidgets import * 
      

      Doing both together does not break anything I do not think but it is a poor coding practice such as:

      from PyQt5.QtCore import QMimeData
      from PyQt5.QtCore import *
      

      As you can see there is no need to do the former if you are doing the latter. Just a few up front pointers I will see I can figure out the issue you are having with drag/drop.

      madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

      1 Reply Last reply
      0
      • DenniD Offline
        DenniD Offline
        Denni
        wrote on last edited by Denni
        #3

        Okay first I copied your code as is and ran it on my Python 3.7 / PyQt5 / Windows 10 system and it works just fine other the Window Title not getting set. Then I cleaned up the code by applying the K.I.S.S principle and it still works just looks nicer --- now if you are running an earlier version of python (my first guess) or a different operating system (maybe but doubt it) perhaps there in lies your issue otherwise I have included the cleaned up code below. Oh and the Title works in this one. Note I did not clean up everything just the main call -- the Main Window class -- and the import statements

        import sys
        
        from PyQt5.QtCore    import Qt, QMimeData, QLocale
        from PyQt5.QtGui     import QStandardItemModel, QStandardItem
        from PyQt5.QtWidgets import QApplication, QMainWindow, QAbstractItemView, QTreeView
        
        class SceneTreeModel(QStandardItemModel):
            def mimeData(self, indexes):
                name = indexes[0].data()
                print('called mimeData on ' + name)
                mimedata = QMimeData()
                mimedata.setText(name)
                return mimedata
        
            def supportedDropActions(self):
                return Qt.MoveAction
        
            def canDropMimeData(self, data, action, row, column, parent):
                print('can drop called on')
                print(parent.data())
                return True
        
            def dropMimeData(self, data, action, row, column, parent):
                parent_name = parent.data()
                node_name = data.text()
                print("Dropped {} onto {}".format(node_name, parent_name))
                return True
        
        def give_model():
            model = SceneTreeModel()
            # create a tree item
            item1 = QStandardItem('item1')
            item2 = QStandardItem('item2')
            item3 = QStandardItem('item3')
        
            model.invisibleRootItem().appendRow(item1)
            item1.appendRow(item2)
            model.invisibleRootItem().appendRow(item3)
        
            return model
        
        class UI_MainWindow(QMainWindow):
            def __init__(self, parent=None):
                super(UI_MainWindow, self).__init__(parent)
                Left = 250
                Top = 100
                Width = 250
                Height = 300
                self.setGeometry(Left, Top, Width, Height)
                self.setWindowTitle("MainWindow")
                self.setLocale(QLocale(QLocale.English, QLocale.UnitedStates))
        
                self.treeView = QTreeView(self)
                self.treeView.setRootIsDecorated(False)
                self.treeView.setObjectName("treeView")
                self.treeView.header().setVisible(False)
        
                self.setCentralWidget(self.treeView)
        
                self.treeView.setModel(give_model())
                self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
                self.treeView.expandAll()
            
        if __name__ == '__main__':
            MainAppThread = QApplication([])
        
            MainWindow = UI_MainWindow()
            MainWindow.show()
        
            sys.exit(MainAppThread.exec_())
        

        madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

        1 Reply Last reply
        0
        • V Offline
          V Offline
          VirtualFloat
          wrote on last edited by VirtualFloat
          #4

          Hi Denni, thanks looking into this and for cleaning up.

          Unfortunately I still have the same issue, although not every time.

          Even with your clean version of the source code, if you pick up item3 and move it directly onto item2 or item1 then the canDrop event is not called.

          Movie:
          https://www.jottacloud.com/s/169522c904c6cd344dfb4cb72c9d9e99481

          I have been able to re-produce this issue on another windows 10 PC with a different python version (3.6.8) and the same Qt version (5.9.7)

          1 Reply Last reply
          0
          • DenniD Offline
            DenniD Offline
            Denni
            wrote on last edited by Denni
            #5

            Okay so have you tried doing this in python 3.7 with pyqt5 ? I ask that because pyqt5 does not always seem to work well with previous versions of python. I know that they have made ports so that earlier versions of python can run pyqt5 but when I see that and the fact that folks on earlier versions of python experience issues that do not exist when run on python 3.7 then it says to me that while the port exists it is not fully stable so one has to expect oddities (perhaps like this) to spring up from time to time. Also are you using the MacOS as someone I think posted a similar issue that was restricted to just that OS

            Still to me the obvious solution is use Python 3.7 because frankly things are only going to get worse when they upgrade 3.7 to a newer version.

            If your insistent on staying on an earlier version of Python than 3.7 then I strongly suggest creating a Python 3.7 environment so that you can test things like that within that environment to see if the issue exists there for you and if it does not then you will know it is because you are using a previous version of Python and some very in-depth work around is going to be need on your part to fix your issue

            My last statement would be (and its directed at everyone using an earlier version of python) : If you do not like change then do not be a programmer or do stuff within the IT industry as it is a constant series of changes. For instance hardware can become obsolete or at least nearly so within 5 years and there are programs that if not updated cannot run on newer hardware and that is not even taking into account OS changes making some software incompatible. So it is best to embrace change, and adapt to to it quickly. Yes sometimes it is best to delay a bit but when that is done an upgrade plan with a timetable ought to put into place so that the necessary change will take place in a timely manner where the sooner is often the better.

            madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

            1 Reply Last reply
            0
            • V Offline
              V Offline
              VirtualFloat
              wrote on last edited by
              #6

              I always try to use the most recent stable versions.
              I just wanted to make sure that the problem was not due to my PC configuration, so I re-checked on an other PC which as it happened was a few months behind on its updates and thus was running an older python version. This is good because now we know that the issue is not related to the specific python version or the hardware.
              So it is either

              • a mistake from my side
              • an error in Qt present at least in version 5.7.9 in combination with Windows 10.

              In a few days I will see if I can reproduce the issue on Linux as well. if so then I will file it as a bug report.

              1 Reply Last reply
              0
              • DenniD Offline
                DenniD Offline
                Denni
                wrote on last edited by
                #7

                Okay? But as I stated it works perfectly fine for me but then I have a clean install of the latest python 3.7 and and latest pyqt5 so there maybe an issue with that or its a bug they already fixed within the latest version. My guess if you submit this as a bug that because it can be proven to work just fine using the latest code that it will get ignored.

                madness... is like gravity, all takes is a little... push -- like from an unsolvable bug

                1 Reply Last reply
                0
                • V Offline
                  V Offline
                  VirtualFloat
                  wrote on last edited by
                  #8
                  This post is deleted!
                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    VirtualFloat
                    wrote on last edited by
                    #9

                    I was able to reproduce the behavior on both Windows and Linux using different configuration and in python as well as directly in C++ (eliminating pyhton/pyqt).

                    Filed as bug report.

                    https://bugreports.qt.io/browse/QTBUG-76418

                    Will close the issue it here as it is not a python / pyqt -only issue.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved