3

I want to build a window which has no title bar, so i do. But it is not any more draggable. You cannot make my window move from here to there.

I know it is because of me, removing the title bar, but how to fix it?

This is my code:

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QWidget
import sys


def window():
    app = QApplication(sys.argv)
    win = QMainWindow()
    win.setGeometry(300, 300, 300, 300)
    win.setWindowTitle("Test")
    win.setWindowFlags(QtCore.Qt.FramelessWindowHint)

    label = QLabel(win)
    label.setText("Hello world")

    win.show()
    sys.exit(app.exec_())


window()

Any help will be appreciated. Please help me with this...

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

1 Answers1

4

You need to reimplement the mousePress and mouseMove methods of the widget (mouseRelease is technically not mandatory, but is actually required for consistency, as the release event has to be correctly intercepted by Qt to avoid any confusion). The former will get the current cursor position relative to the geometry (self.offset), while the latter will compute the new "window" position by adding the new position to the current one and subtracting the offset.

I would also suggest you to use a QWidget instead of a QMainWindow. While QMainWindow implementation is very similar to that of QWidgets, subclassing a QMainWindow for your purpose might be a bit harder, as it's widget more complex than it seems.
If you only need a QMainWindow to get a status bar, just add a new one to the widget layout; if you also need a menubar, add it to the widget's layout using setMenuBar.

class FramelessWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Test")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.label = QLabel("Hello world", self)
        self.offset = None

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.offset = event.pos()
        else:
            super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.offset is not None and event.buttons() == QtCore.Qt.LeftButton:
            self.move(self.pos() + event.pos() - self.offset)
        else:
            super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.offset = None
        super().mouseReleaseEvent(event)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = FramelessWidget()
    win.setGeometry(300, 300, 300, 300)
    win.show()
    sys.exit(app.exec_())
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • can I customize the close minimize and title bar buttons with my own images ?? Cauz I want to make it's title bar look like macos. –  Nov 17 '19 at 15:50
  • @Andrewwhiteman sorry but I'm a bit confused. You wanted a window without a title bar, why are you asking about buttons that should be part of it? – musicamante Nov 17 '19 at 16:07
  • 1
    @musicamante They probably want a custom title bar, as in [this question](https://stackoverflow.com/q/44241612/984421) and [this question](https://stackoverflow.com/q/9377914/984421). The answers there don't implement window resizing, though, which is another issue with this approach. – ekhumoro Nov 17 '19 at 22:51
  • Yes @ekhumoro you got it right!! I want to have a customized title bar which looks like the title bar on macos. How to do that ?? –  Nov 18 '19 at 07:43
  • 1
    @Andrewwhiteman I don't personally have anything to add that isn't already in the questions I linked to. I suggest you study the answers there and try to implement as much as possible. When you run into problems you can't solve, ask a new question. – ekhumoro Nov 18 '19 at 13:36
  • @Andrewwhiteman I'd like to add [this answer](https://stackoverflow.com/a/57578281/2001654) to those provided by ekhumoro. It's a bit unrelated, as the question was about having the menu bar in the title bar, but the concepts for the custom title bar and its buttons are related to your request; moreover, it uses an actual QMainWindow. I'd also suggest you to be more careful in your future questions, since what you asked in this question is very different from what you've specified in the previous comments. – musicamante Nov 18 '19 at 14:04
  • Sorry for that! I realized it and posted another question. –  Nov 18 '19 at 14:28