首页 > 解决方案 > 如何使新窗口相对于 PyQt 中的主窗口居中?

问题描述

如何更改我的代码以显示Loading在相对于屏幕上MainWindow任何位置的中心?MainWindow

它现在所做的是将加载动画放在左上角,忽略 MainWindow 的位置。

即使我将几何图形添加到 MainWindow,结果也是一样的。

这是代码,这两个类都是从 py.file 导入的:

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
                    
        self.loading = Loading(parent=self)
        self.ui.check.clicked.connect(self.show_animation)


        self.show()


    def show_animation(self):
        self.loading.show()


class Loading(QWidget):
    def __init__(self, parent=None):
        self.parent = parent
        QWidget.__init__(self)
        self.ui = Ui_loading()
        self.ui.setupUi(self)

        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        
        self.label_animation = QLabel(self)
        self.label_animation.setGeometry(QtCore.QRect(25, 25, 256, 256))
        self.movie = QMovie('giphy1.gif')
        self.label_animation.setMovie(self.movie)
        self.movie.start()

        geo = self.geometry()
        geo.moveCenter(self.parent.geometry().center())
        self.setGeometry(geo)

标签: pyqtwindowparent-childparent

解决方案


您的代码不起作用,因为您在创建Loading实例时已经在设置几何图形,而且还为时过早:不仅当您单击按钮时,父窗口可能已被移动或调整大小,而且您正在创建甚至尚未显示的实例,因此它仍然具有默认几何图形(通常为 640x480,除非它具有基于其内容的最小或最大尺寸限制)。

为了使小部件在父级上居中,您必须在显示时考虑几何图形。

class Loading(QWidget):
    # ...
    def showEvent(self, event):
        if not event.spontaneous():
            geo = self.geometry()
            geo.moveCenter(self.parent.geometry().center())
            QtCore.QTimer.singleShot(0, lambda: self.setGeometry(geo))

进行检查event.spontaneous()是为了仅在显式显示(使用show()or setVisible(True))时移动窗口,否则在任何情况下都会发生这种情况,例如在最小化窗口后恢复窗口时。
延迟setGeometry()是必需的,因为在某些情况下(最常见的是在 Linux 上)在 Qt 向底层窗口系统发出请求和窗口实际映射到屏幕上的那一刻之间需要一些时间。


推荐阅读