pythonpython-3.xpyqtpyqt5qmdiarea

QMdiArea Leaving the window


Is it possible to prevent the windows created in the QMdiArea from going out of the window down or sideways? Like the blocking there is to take it out upwards. At the moment it is possible to pull out the whole window of the QMdiArea.

Edit: Is it possible to detect window collisions?

Not necessarily to prevent it from overlapping, but that it is somehow attracted by the other window.

import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets

class MainWindow(QtWidgets.QMainWindow):
    count = 0
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        bar = self.menuBar()
        file = bar.addMenu("Subwindow")
        file.addAction("window1")
        file.addAction("text1")
        file.addAction("text2")
        file.triggered[QAction].connect(self.click)
        self.setWindowTitle("Multiple window using MDI")

    def click(self, q):
        print("New sub window")
        if q.text() == "window1":
            MainWindow.count = MainWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("subwindow" + str(MainWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()

        if q.text() == "text1":
            self.mdi.cascadeSubWindows()

        if q.text() == "text2":
            self.mdi.tileSubWindows()

def main():
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Solution

  • You could intercept the moveEvent on QMdiSubWindow and check the position of the window against the size of the QMdiArea. If it's out of bounds, move the window back in bounds.

    An example which only checks the right bound (you can implement the rest easily enough from there) -

    class SubWindow(QtWidgets.QMdiSubWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
    
        def moveEvent(self, event):
            pos = event.pos()
            right = pos.x() + self.width()
            area = self.mdiArea()
            
            if right > area.width():
                self.move(area.width() - self.width(), pos.y())
                return