2

I have this sample code on how to drag and move a QPushButton. The only issue of that code is, when you drag the button and release it, the button status is stay as checked.

Can someone help me to change the code so that, after drag the button and release the button status is automatically unchecked. So, I don't have to click it to uncheck it.

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtCore import Qt

class DragButton(QPushButton):

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        super(DragButton, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)
            self.move(newPos)

            self.__mouseMovePos = globalPos

        super(DragButton, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos 
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(DragButton, self).mouseReleaseEvent(event)

def clicked():
    print ("click as normal!")

if __name__ == "__main__":
    app = QApplication([])
    w   = QWidget()
    w.resize(800,600)

    button = DragButton("Drag", w)
    button.clicked.connect(clicked)

    w.show()
    app.exec_() 
Dr. Zezo
  • 395
  • 2
  • 17
  • I'm confused. Do you want to keep the clicking feature and still be able to move the button by dragging it if the mouse beyond the manhattan length? – musicamante Nov 30 '19 at 14:14
  • No, what I want simply is, when i release the button after dragging, the button status become normal "unchecked". If you noticed, when you drag the button, and then release, the button still clicked, I just want to remove this click automatically after releasing. Hope I could explain it better – Dr. Zezo Nov 30 '19 at 15:00

1 Answers1

1

You return in the mouseReleaseEvent, which means that you're not letting the button know that it actually received a mouse release, thus leaving the status as pressed.

def mouseReleaseEvent(self, event):
    if self.__mousePressPos is not None:
        moved = event.globalPos() - self.__mousePressPos 
        if moved.manhattanLength() > 3:
            event.ignore()
            return # <-- the problem is here!

    super(DragButton, self).mouseReleaseEvent(event)

You can see that it behaves correctly if you move the mouse by just a few pixels (below the Manhattan length), so you'll have to completely remove that if block, or call self.setDown(False) before returning if you want to avoid sending the clicked signal.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • You're welcome! Remember to mark the answer as accepted (the check on the left of the answer) since it solved your problem. – musicamante Nov 30 '19 at 15:40