PyQt5 立即显示 QMessageBox 和 QInputDialog



我很好奇是什么让QInputDialog和QMessageBox.question总是立即显示?对于其他 PyQT 元素,需要显示 UI 内容所需的初始序列。

# Example of a Basic PyQT5 UI Application
app = QApplication(sys.argv)
w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

我一直在努力寻找合适的文档,但没有看到任何突出的内容。所以我希望有人能指出我应该如何修改小部件类,或者在哪里可以找到合适的文档。

from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QLabel, QMessageBox, QHBoxLayout, QInputDialog
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtGui import QIcon, QPixmap
class QuestionPopup(QWidget):
def __init__(self, question = None):
super().__init__()
self.title = 'Question Popup'
self.left = 250
self.top = 50
self.width = 320
self.height = 200
self.question = question
self._response = None
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
buttonReply = QMessageBox.question(self, 'PyQt5 message', self.question, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if buttonReply == QMessageBox.Yes:
self.response = True
else:
self.response = False
self.show() 
def getText(self):
text, okPressed = QInputDialog.getText(self, "Get text","Your name:", QLineEdit.Normal, "")
if okPressed and text != '':
print(text)

我的目标是创建自定义对话框,这些对话框将显示图像并要求用户输入有关图像的信息。我的代码非常复杂,我不能简单地显示一个新的UI窗口。我需要允许QMessageBox和QInputDialog立即出现的功能。

您的问题中引用的方法都是 QInputDialog 和 QMessageBox 的静态成员,它们是同步的阻塞调用。这是通过调用 show 而不是调用 show,在对话框上调用 exec 来模拟的。exec 类似于 show(在 Pyqt 中,exec_ exec 以避免与 Python 内置的 exec 发生冲突(,但它实际上会阻止所有其他 UI 组件,直到它提供控制权(从技术上讲,它通过暂停主事件循环并运行它自己的特定对话框来做到这一点,最终放弃控制权(。在此处查看有关此内容的更多信息:https://doc.qt.io/qt-5/qmessagebox.html#exec

请注意,这是特定于上述这些静态函数的行为。您可以在不使用这些功能的情况下创建自己的 QMessageBox,它将以正常方式运行,即在您显式调用 show 之前不会显示。

下面是一个示例函数,它显示了如何在后台实现 QMessageBox.static 的高级详细信息(尽管这不是实际的代码(:

def question(parent, title, message, buttons):
message_box = QMessageBox(question_icon, title, message, buttons)
return message_box.exec_()

要点是获取这些静态函数正在使用的行为,您需要在对话框上调用exec_而不是显示。请注意,exec_仅适用于特定的小部件类型,最明显的是从QDialog继承的任何内容。您还应该注意 exec 是一个同步的阻塞调用,这意味着在处理该对话框之前,在应用程序主线程上运行的任何其他内容都不会运行。

正如@TheKewlStore所说,您引用的方法是静态的,并且限制您可以修改的内容。它们包含内置属性,可使它们立即显示,而不是需要使用show()app.exec_()下面解决了您问题的这一部分:"...如何修改小部件类"以显示图像并允许用户输入以及显示消息框。

这将从创建一个简单的消息框开始,然后在关闭时,将创建并显示一个基本对话框,该对话框可以显示图像,指示用户的文本行,用户输入文本的位置,以及确定和取消按钮 - 我只连接了确定按钮以简单地打印用户的输入。显然,您可以插入所需的按钮命令以及用户输入会发生什么。我还使用了一些网格布局,主要是因为我喜欢它保持东西干净的方式,但它们并不是完成这项工作的强制性要求。还可以使盒子的尺寸更加动态,我只是觉得这里不需要它。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets, QtCore
import PyQt5
import os
class MsgBox(object):
def setupUi(self, show_msgbox):
show_msgbox.setObjectName("show_msgbox")
show_msgbox.setText('Show your message text here')
class MsgPrompt(PyQt5.QtWidgets.QMessageBox, MsgBox):
app = PyQt5.QtWidgets.QApplication(sys.argv)
def __init__(self):
super(MsgPrompt, self).__init__()
self.setupUi(self)
super(MsgPrompt, self).exec_()
class UserInput(object):
def setupUi(self, get_user_input):
# Basic shape
self.width = 425
get_user_input.setObjectName("get_user_input")
get_user_input.resize(425, self.width)
self.frame = QtWidgets.QFrame(get_user_input)
self.frame.setGeometry(QtCore.QRect(11, 10, 401, 381))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.frame.setObjectName("frame")
# Creating the grid layout for most of the display elements
self.gridLayoutWidget = QtWidgets.QWidget(self.frame)
self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 381, 361))
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.get_user_input_layout = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.get_user_input_layout.setContentsMargins(5, 5, 5, 5)
self.get_user_input_layout.setObjectName("get_user_input_layout")
# Grid layout for the buttons
self.buttonLayoutGrid = QtWidgets.QWidget(get_user_input)
self.buttonLayoutGrid.setGeometry(QtCore.QRect(10, 390, 401, 41))
self.buttonLayoutGrid.setObjectName("buttonLayoutGrid")
self.buttonLayout = QtWidgets.QGridLayout(self.buttonLayoutGrid)
self.buttonLayout.setContentsMargins(0, 0, 0, 0)
self.buttonLayout.setObjectName("buttonLayout")
# Adding buttons    
self.buttonOK = QtWidgets.QPushButton(self.buttonLayoutGrid)
self.buttonOK.setObjectName("buttonOK")
self.buttonOK.setText("OK")
self.buttonLayout.addWidget(self.buttonOK, 0, 1, 1, 1)
self.buttonCancel = QtWidgets.QPushButton(self.buttonLayoutGrid)
self.buttonCancel.setObjectName("buttonCancel")
self.buttonCancel.setText("CANCEL")
self.buttonLayout.addWidget(self.buttonCancel, 0, 2, 1, 1)
# Adding the place for the image
self.image = QtWidgets.QLabel(self.gridLayoutWidget)
self.get_user_input_layout.addWidget(self.image, 0, 0, 1, 1)
# Add instructions for the user
self.user_prompt_text = QtWidgets.QLabel(self.gridLayoutWidget)
self.user_prompt_text.setText('WHAT IS THIS PIC?')
self.user_prompt_text.setAlignment(PyQt5.QtCore.Qt.AlignLeft)
self.get_user_input_layout.addWidget(self.user_prompt_text, 1, 0, 1, 1)
# Add a field for the user to enter text    
self.user_input_box = PyQt5.QtWidgets.QLineEdit(self.gridLayoutWidget)
self.user_input_box.setObjectName('user_input_box')
self.user_input_box.setEnabled(True)
self.get_user_input_layout.addWidget(self.user_input_box, 2, 0, 1, 1)
# This is an optional call
QtCore.QMetaObject.connectSlotsByName(get_user_input)
class UserInputPrompt(PyQt5.QtWidgets.QDialog, UserInput):
app = PyQt5.QtWidgets.QApplication(sys.argv)
def __init__(self, path_to_image):
super(UserInputPrompt, self).__init__()
self.setupUi(self)
self.path_to_image = path_to_image
self.user_input_box.setFocus()
self.buttonOK.clicked.connect(self.get_user_input)
self.image.setPixmap(PyQt5.QtGui.QPixmap(self.path_to_image).scaledToWidth(self.width
self.image.show()
super(UserInputPrompt, self).exec_()        
def get_user_input(self):
print(self.user_input_box.text())
MsgPrompt()
UserInputPrompt('your_image_file.jpg')

最新更新