Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?
Forum Updated to NodeBB v4.3 + New Features

[PyQt5] What is the right way to discretize a QDrag pixmap along a grid?

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 3 Posters 341 Views 1 Watching
  • 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.
  • Simon_tries_hardS Offline
    Simon_tries_hardS Offline
    Simon_tries_hard
    wrote on last edited by
    #1

    Hi everyone, I hope I'm at the right address as I'm new to this forum (and forums in general). I've asked the same question on StackOverflow but it received no attention there.

    The following code produces a simple applet with a button that we can make copies of by dragging and dropping it.

    import sys
    import math
    from PyQt5.QtCore import QMimeData, QPoint, Qt
    from PyQt5.QtGui import QColor, QDrag, QPainter
    from PyQt5.QtWidgets import QApplication, QPushButton, QWidget
    
    class Button(QPushButton):
        def mouseMoveEvent(self, e):
            if e.buttons() != Qt.LeftButton:
                return
            mimeData = QMimeData()
            mimeData.setText('%d,%d' % (e.x(), e.y()))
            pixmap = QWidget.grab(self)
            painter = QPainter(pixmap)
            painter.setCompositionMode(painter.CompositionMode_DestinationIn)
            painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127))
            painter.end()
            drag = QDrag(self)
            drag.setMimeData(mimeData)
            drag.setPixmap(pixmap)
            drag.setHotSpot(e.pos())
            if drag.exec_(Qt.CopyAction) == Qt.CopyAction:
                print('Button has been copied!')
    
    class Example(QWidget):
        def __init__(self):
            super(Example, self).__init__()
            self.initUI()
    
        def initUI(self):
            self.setAcceptDrops(True)
            button = Button('Button', self)
            button.resize(100, 30)
            self.buttons = [button]
            self.setWindowTitle('Create new buttons')
            self.setGeometry(300, 300, 300, 300)
    
        def dragEnterEvent(self, e):
            e.accept()
    
        def dropEvent(self, e):
            mime = e.mimeData().text()
            relx, rely = map(int, mime.split(','))
            button = Button('Copied button', self)
            button.resize(100, 30)
            xcoord = e.pos().x() - relx
            xcoord = math.floor(0.5 + xcoord / 100) * 100
            ycoord = e.pos().y() - rely
            ycoord = math.floor(0.5 + ycoord / 30) * 30
            button.move(QPoint(xcoord, ycoord))
            button.show()
            self.buttons.append(button)
            e.setDropAction(Qt.CopyAction)
            e.accept()
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Example()
        ex.show()
        app.exec_()
    

    The definition of xcoord and ycoord cause the dropped copy of the button to automatically align with a simple grid. I would like the location of pixmap, which currently traces the mouse as we perform our drag and drop, to be discretized, so that it is located where the button would land when I would drop the button.

    While experimenting, I learned that, while dragging, the mouse coordinates are not being kept track of automatically; one has to reimplement self.dragMoveEvent() to do so. I've tried to use this to continually update the coordinates of drag.setHotSpot(), but without results.

    I am aware that PyQt5 has numerous options for implementing grid layouts, which I feel is the right way to proceed, but I have no idea how to do so.

    jsulmJ 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to the forums.
      You app really sound like this exmaple
      https://doc.qt.io/qtforpython/overviews/qtwidgets-draganddrop-puzzle-example.html
      where you can drag an image piece to a grid.
      However, it uses a list of taken positions so not sure that will work for your use case ?

      Just to understand it right. While dragging, you want the cursor to sort of jump to grid locations ?

      Simon_tries_hardS 1 Reply Last reply
      0
      • Simon_tries_hardS Simon_tries_hard

        Hi everyone, I hope I'm at the right address as I'm new to this forum (and forums in general). I've asked the same question on StackOverflow but it received no attention there.

        The following code produces a simple applet with a button that we can make copies of by dragging and dropping it.

        import sys
        import math
        from PyQt5.QtCore import QMimeData, QPoint, Qt
        from PyQt5.QtGui import QColor, QDrag, QPainter
        from PyQt5.QtWidgets import QApplication, QPushButton, QWidget
        
        class Button(QPushButton):
            def mouseMoveEvent(self, e):
                if e.buttons() != Qt.LeftButton:
                    return
                mimeData = QMimeData()
                mimeData.setText('%d,%d' % (e.x(), e.y()))
                pixmap = QWidget.grab(self)
                painter = QPainter(pixmap)
                painter.setCompositionMode(painter.CompositionMode_DestinationIn)
                painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127))
                painter.end()
                drag = QDrag(self)
                drag.setMimeData(mimeData)
                drag.setPixmap(pixmap)
                drag.setHotSpot(e.pos())
                if drag.exec_(Qt.CopyAction) == Qt.CopyAction:
                    print('Button has been copied!')
        
        class Example(QWidget):
            def __init__(self):
                super(Example, self).__init__()
                self.initUI()
        
            def initUI(self):
                self.setAcceptDrops(True)
                button = Button('Button', self)
                button.resize(100, 30)
                self.buttons = [button]
                self.setWindowTitle('Create new buttons')
                self.setGeometry(300, 300, 300, 300)
        
            def dragEnterEvent(self, e):
                e.accept()
        
            def dropEvent(self, e):
                mime = e.mimeData().text()
                relx, rely = map(int, mime.split(','))
                button = Button('Copied button', self)
                button.resize(100, 30)
                xcoord = e.pos().x() - relx
                xcoord = math.floor(0.5 + xcoord / 100) * 100
                ycoord = e.pos().y() - rely
                ycoord = math.floor(0.5 + ycoord / 30) * 30
                button.move(QPoint(xcoord, ycoord))
                button.show()
                self.buttons.append(button)
                e.setDropAction(Qt.CopyAction)
                e.accept()
        
        if __name__ == '__main__':
            app = QApplication(sys.argv)
            ex = Example()
            ex.show()
            app.exec_()
        

        The definition of xcoord and ycoord cause the dropped copy of the button to automatically align with a simple grid. I would like the location of pixmap, which currently traces the mouse as we perform our drag and drop, to be discretized, so that it is located where the button would land when I would drop the button.

        While experimenting, I learned that, while dragging, the mouse coordinates are not being kept track of automatically; one has to reimplement self.dragMoveEvent() to do so. I've tried to use this to continually update the coordinates of drag.setHotSpot(), but without results.

        I am aware that PyQt5 has numerous options for implementing grid layouts, which I feel is the right way to proceed, but I have no idea how to do so.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Simon_tries_hard said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:

        one has to reimplement self.dragMoveEvent() to do so

        I don't see it in the code you posted.
        I also don't understand why you're constantly creating QDrag while moving mouse with pressed left button.
        And you do not accept/reject the mouse move event.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • mrjjM mrjj

          Hi and welcome to the forums.
          You app really sound like this exmaple
          https://doc.qt.io/qtforpython/overviews/qtwidgets-draganddrop-puzzle-example.html
          where you can drag an image piece to a grid.
          However, it uses a list of taken positions so not sure that will work for your use case ?

          Just to understand it right. While dragging, you want the cursor to sort of jump to grid locations ?

          Simon_tries_hardS Offline
          Simon_tries_hardS Offline
          Simon_tries_hard
          wrote on last edited by
          #4

          @mrjj said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:

          Just to understand it right. While dragging, you want the cursor to sort of jump to grid locations ?

          While dragging, a 'ghost' instance of the button (the pixmap which is made to resemble the button but with added transparency) appears behind the cursor. I want this ghost instance to jump from grid location to grid location as I'm moving the mouse.

          @jsulm said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:

          @Simon_tries_hard said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:

          one has to reimplement self.dragMoveEvent() to do so

          I don't see it in the code you posted.
          I also don't understand why you're constantly creating QDrag while moving mouse with pressed left button.
          And you do not accept/reject the mouse move event.

          The code I posted is what I started with. I tweaked it around in various ways with no good results, but I didn't post the changed codes.

          As for the rest of what you say, well, I'm a newbie when it comes to Qt so whatever you don't understand I probably understand even less.

          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