4

So I have a frameless QDialog that I want to be able to move around simply by clicking and dragging it. Given the code below, dragging the dialog always snaps the very top-left (0,0) of the dialog to the mouse. How might I circumvent this, or rather, what might the math be for it?

Standard QDialog with the following basic subclass:

class Main(QtGui.QDialog):
    def __init__(self, args):
        QtGui.QDialog.__init__(self)

    def mouseMoveEvent(self, event):
        super(Main, self).mouseMoveEvent(event)
        if self.leftClick == True: self.moveWindow(event.globalPos())

    def mousePressEvent(self, event):
        super(Main, self).mousePressEvent(event)
        if event.button() == QtCore.Qt.LeftButton:
            self.leftClick = True

    def mouseReleaseEvent(self, event):
        super(Main, self).mouseReleaseEvent(event)
        self.leftClick = False
Cryptite
  • 1,426
  • 2
  • 28
  • 50

2 Answers2

2

Proposed solution moves Window, but mouse cursor jumps to 0,0 of Window. I wanted mouse cursor to stay on x,y of the Window all the time.

Here is upgraded version of the code [in QT5]:

X=0
X2=8  #!!!!
Y=0
Y2=30 #!!!!
class Main(QtWidgets.QMainWindow):
    leftClick = False #! IMPORTANT

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

    def mouseMoveEvent(self, event):
        super(Main, self).mouseMoveEvent(event)
        if self.leftClick == True: 
            self.move(event.globalPos().x()-X-X2,event.globalPos().y()-Y-Y2)

    def mousePressEvent(self, event):
        super(Main, self).mousePressEvent(event)
        if event.button() == QtCore.Qt.LeftButton:
            self.leftClick = True
            global X,Y
            X=event.pos().x()
            Y=event.pos().y()

    def mouseReleaseEvent(self, event):
        super(Main, self).mouseReleaseEvent(event)
        self.leftClick = False

For frameless window (made with window.setMask()) I need some constants like X2 and Y2, because "masked" frameless window is a bit smaller than a real framed window. Don't know how to calculate this difference yet.

UP. After long time I've found one critical bug. If you press Left Mouse Button on any pushbutton (just after the application start) and drag the mouse cursor away from that pushbutton, your application will crash, because we refer to nonexistent variable LeftClick. That's why in class Main we need to create LeftClick.

Devilhunter
  • 123
  • 2
  • 11
2

Instead of event.pos(), try calling event.globalPos(). From the QMouseEvent reference, "If you move the widget as a result of the mouse event, use the global position returned by globalPos() to avoid a shaking motion."

Stephen Terry
  • 6,169
  • 1
  • 28
  • 31
  • Excellent! That worked, I've updated my code above to show where I'm at so far. Now I need to be able to grab the mouse where it is in relation to the dialog, as whenever I left-click to drag the dialog around, the top-left of the dialog snaps to the mouse. – Cryptite Apr 28 '11 at 21:59
  • do you have solved that problem? my mouse snaps to the top-left of the dialog too.. i can't get rid of it – apelliciari May 23 '11 at 15:56
  • No I have not yet, I've just dealt with it sticking for now. Hopefully somebody can come along and help out. – Cryptite Jul 27 '11 at 20:18
  • Hey I encountered the same problem and solved it. Store the coordinates of the first click in mousePressEvent: `self.clickX = event.x() self.clickY = event.y()` Then, move the window with a correction for the initial click location: `self.move(event.globalPos(event.globalX-self.clickX, event.globalY-self.clickY)` – Junuxx May 19 '12 at 20:05