Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Dragable pyqt frameless app



  • Morning.

    I have built an app with Qdesigner, with pyuic I created python code and made the app frameless. I added a qframe as a title bar which contains two qlabels, for icon and app info, and I added two qtoolbuttons for minimizing and close app. I need this bar title let me to move the app.

    How's that Possible?

    thank you very much


  • Lifetime Qt Champion

    @arkero24 Take a look at https://doc.qt.io/qt-5/qwidget.html#mouseMoveEvent
    You will need to store last mouse cursor position, then next time mouseMoveEvent is called you calculate mouse cursor position difference (current - last) and apply this difference to move your window.



  • @arkero24
    Check this out: https://www.learnpyqt.com/apps/build-desktop-notes-application/
    Maybe that's what you're looking for.


  • Banned

    @arkero24 first and foremost I would strongly suggest that you stop using the QDesigner and learn to code a pyqt window from scratch -- it is extremely easy and once learned takes no more real time than using the Designer does but what you end up with not only do you fully understand how it works but you can freely interact with that code to enhance it or tweak it as you wish -- rather than having some mysterious black-box untouchable code that is extremely difficult to understand what its doing and/or how to work with it nicely

    Next to truly help you with this issue it would be best if you supplied a Minimal Reproducible Example of your issue so that we can copy/paste/run it and more easily discern where you issue might reside.



  • Here's a draggable frameless widget that might be a useful starting point for you. It uses mouseMoveEvent() to move itself when dragged.

    class Marker(W.QWidget):
      def __init__(self, parent = None):
          W.QWidget.__init__(self, parent)
          self.setWindowFlags(QtCore.Qt.Widget | QtCore.Qt.FramelessWindowHint);
          self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True);
          self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True);
          self.clicked = False
      def paintEvent(self, ev):
          p = Gui.QPainter(self)
          p.fillRect(self.rect(), Gui.QColor(128, 128, 128, 128))
          
      def mousePressEvent(self, ev):
          self.old_pos = ev.screenPos()
    
      def mouseMoveEvent(self, ev):
          if self.clicked:
            dx = self.old_pos.x() - ev.screenPos().x()
            dy = self.old_pos.y() - ev.screenPos().y()
            self.move(self.pos().x() - dx, self.pos().y() - dy)
          self.old_pos = ev.screenPos()
          self.clicked = True
          return W.QWidget.mouseMoveEvent(self, ev)
    
    

  • Banned

    And here is a MUC of @wrosecrans above code with a close button tossed in -- just copy/paste and run

    from PyQt5.QtCore    import Qt
    from PyQt5.QtGui     import QPainter, QColor
    from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
    from PyQt5.QtWidgets import QPushButton
    
    from sys import exit as sysExit
    
    class Marker(QWidget):
        def __init__(self):
            QWidget.__init__(self)
    
            self.setWindowFlags(Qt.Widget | Qt.FramelessWindowHint);
            self.setAttribute(Qt.WA_NoSystemBackground, True);
            self.setAttribute(Qt.WA_TranslucentBackground, True);
            self.clicked = False
            self.resize(350, 250)
    
            self.btnClose = QPushButton('Close')
            self.btnClose.clicked.connect(self.CloseApp)
    
            HBox = QHBoxLayout()
            HBox.addWidget(self.btnClose)
            HBox.addStretch(1)
    
            VBox = QVBoxLayout()
            VBox.addLayout(HBox)
            VBox.addStretch(1)
    
            self.setLayout(VBox)
          
        def CloseApp(self):
            sysExit()
    
        def paintEvent(self, event):
            p = QPainter(self)
            p.fillRect(self.rect(), QColor(128, 128, 128, 128))
    
        def mousePressEvent(self, event):
            self.old_pos = event.screenPos()
    
        def mouseMoveEvent(self, event):
            if self.clicked:
                dx = self.old_pos.x() - event.screenPos().x()
                dy = self.old_pos.y() - event.screenPos().y()
                self.move(self.pos().x() - dx, self.pos().y() - dy)
            self.old_pos = event.screenPos()
            self.clicked = True
    
            return QWidget.mouseMoveEvent(self, event)
          
    if __name__ == "__main__":
        MainEventThred = QApplication([])
    
        MainApp = Marker()
        MainApp.show()
    
        MainEventThred.exec()
    
      # If anyone wants more extensive free help I run an online lab-like classroom-like 
      # message server feel free and drop by you will not be able to post until I clear 
      # you as a student as this prevents spammers so if interested here is the invite
      # https://discord.gg/3D8huKC
    

Log in to reply