python - 如何使QMessageBox和QInputDialog在屏幕上居中?

标签 python pyqt pyqt5 qmessagebox qinputdialog

我有这个函数可以将对象置于屏幕中央。

我想将 QMainWindow、QInputDialog 和 QMessageBox 居中。

这是我的消息框:

def _Warning(self,_type):
        infoBox = QtWidgets.QMessageBox()
        infoBox.setIcon(QtWidgets.QMessageBox.Warning)
        infoBox.setWindowTitle("Warning")
        if (_type=="File"):
            infoBox.setText("The File Already exist in the current Directory")
        else:
            infoBox.setText("The Folder Already exist in the current Directory")

        self.center(infoBox)

        infoBox.exec_()

这是我的 QInputDialog:

def AddFile_B(self):
        self.cuadro = QInputDialog()
        self.center(self.cuadro)
        text, okPressed = self.cuadro.getText(self, "New File","File Name:", QLineEdit.Normal, "")
        if okPressed and text != '':
            file = File_Node(text)
            verify = self.bonsai_B.addChild(file)
            if (verify == True):
                item = QtWidgets.QListWidgetItem(None,0)
                self.TreeB.addItem(item)
            else:
                del file
                self._Warning("File")

这是我的中心功能:

def center(self,object):
    qtRectangle = object.frameGeometry() 
    centerPoint = QtWidgets.QDesktopWidget().availableGeometry().center()
    qtRectangle.moveCenter(centerPoint)
    object.move(qtRectangle.topLeft())

我只能将 QMainWindow 居中。

逻辑是将对象移动到左上点(screenWidth/2 - objectWidth/2、screenHeight/2 - objectHeight/2),但我不知道我做错了什么。

最佳答案

-QMessageBox

对于QMessageBox,它在exec_()方法中调整大小,因此可能的解决方案是使用QTimer.singleShot() 在显示后立即更改几何图形。

from functools import partial
from PyQt5 import QtCore, QtWidgets


def center(window):
    # https://wiki.qt.io/How_to_Center_a_Window_on_the_Screen

    window.setGeometry(
        QtWidgets.QStyle.alignedRect(
            QtCore.Qt.LeftToRight,
            QtCore.Qt.AlignCenter,
            window.size(),
            QtWidgets.qApp.desktop().availableGeometry(),
        )
    )


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.btn_warning = QtWidgets.QPushButton(
            "Open QMessageBox", clicked=self.open_qmessagebox
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.btn_warning)

        center(self)

    @QtCore.pyqtSlot()
    def open_qmessagebox(self):
        infoBox = QtWidgets.QMessageBox()
        infoBox.setIcon(QtWidgets.QMessageBox.Warning)
        infoBox.setWindowTitle("Warning")
        infoBox.setText("The XXX Already exist in the current Directory")
        wrapper = partial(center, infoBox)
        QtCore.QTimer.singleShot(0, wrapper)
        infoBox.exec_()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

-QInputDialog

对于 QInputDialog,QInputDialog::getText() 方法是静态的,因此“self.cuadro”对象不是窗口,因为窗口是在该方法中创建的。如果您将父级传递给 getText(),那么默认情况下它将相对于该父级居中。

因此,如果 QMainWindow 居中并假设 QMainWindow 是 self,则无需修改任何内容。

如果父级不在屏幕中央,则有 2 种可能的解决方案:

  • 不要使用静态方法并通过 QInputDialog 实例实现逻辑:
from functools import partial
from PyQt5 import QtCore, QtWidgets


def center(window):
    # https://wiki.qt.io/How_to_Center_a_Window_on_the_Screen

    window.setGeometry(
        QtWidgets.QStyle.alignedRect(
            QtCore.Qt.LeftToRight,
            QtCore.Qt.AlignCenter,
            window.size(),
            QtWidgets.qApp.desktop().availableGeometry(),
        )
    )


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.btn_inputdialog = QtWidgets.QPushButton(
            "Open QInputDialog", clicked=self.open_qinputdialog
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.btn_inputdialog)

        center(self)

    @QtCore.pyqtSlot()
    def open_qinputdialog(self):
        dialog = QtWidgets.QInputDialog(self)
        dialog.setWindowTitle("New File")
        dialog.setLabelText("File Name:")
        dialog.setTextEchoMode(QtWidgets.QLineEdit.Normal)
        dialog.setTextValue("")
        wrapper = partial(center, dialog)
        QtCore.QTimer.singleShot(0, wrapper)
        text, okPressed = (
            dialog.textValue(),
            dialog.exec_() == QtWidgets.QDialog.Accepted,
        )
        if okPressed and text:
            print(text)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
  • 继续使用静态方法并使用 findChildren() 获取窗口
from functools import partial
from PyQt5 import QtCore, QtWidgets


def center(window):
    # https://wiki.qt.io/How_to_Center_a_Window_on_the_Screen

    window.setGeometry(
        QtWidgets.QStyle.alignedRect(
            QtCore.Qt.LeftToRight,
            QtCore.Qt.AlignCenter,
            window.size(),
            QtWidgets.qApp.desktop().availableGeometry(),
        )
    )


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.btn_inputdialog = QtWidgets.QPushButton(
            "Open QInputDialog", clicked=self.open_qinputdialog
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.btn_inputdialog)

        center(self)

    @QtCore.pyqtSlot()
    def open_qinputdialog(self):
        parent = self
        dialogs = parent.findChildren(QtWidgets.QInputDialog)

        def onTimeout():
            dialog, *_ = set(parent.findChildren(QtWidgets.QInputDialog)) - set(dialogs)
            center(dialog)

        QtCore.QTimer.singleShot(0, onTimeout)
        text, okPressed = QtWidgets.QInputDialog.getText(
            parent, "New File", "File Name:", QtWidgets.QLineEdit.Normal, ""
        )
        if okPressed and text:
            print(text)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

关于python - 如何使QMessageBox和QInputDialog在屏幕上居中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57742263/

相关文章:

python - Raspberry Pi 上的 PyQt5 Python 线程 RFID

python - Mayavi:自定义工具栏

python - 检查列表中的任何相邻整数是否相等

python - 检查字符串为 1, 0 否则打印字符串

python - 如何在 Django Channels 中创建服务器端计时器/倒计时?

python - 属性错误: 'OAndX' object has no attribute 'run'

qt - 有没有使用 PyQt/PySide 开发的真正现代、美观的桌面应用程序?

python - 基于 PyQt 的 GUI 中的计时器

python - 在不使用 sys.exit() 的情况下关闭 ipython 笔记本中的 pyqt 小部件

python - PyQt - 主要卡在 QThread 上