如何使 QMessageBox 和 QInputDialog 在屏幕上居中?
How to center QMessageBox and QInputDialog on the screen?
我有这个功能可以让一个对象在屏幕中间居中。
我想将 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 居中。
逻辑是将物体移动到topLeft Point (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" 对象不是 window,因为 window 是在其中创建的方法。如果您将父级传递给 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()
获取 window
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_())
我有这个功能可以让一个对象在屏幕中间居中。
我想将 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 居中。
逻辑是将物体移动到topLeft Point (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" 对象不是 window,因为 window 是在其中创建的方法。如果您将父级传递给 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() 获取 window
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_())