python - 如何创建带有任意数量按钮的弹出窗口?
问题描述
在 PyQt5 中,我试图创建一个类来实现带有任意数量按钮的弹出窗口。我认为我已经接近了,但是当我显示这个东西时,消息和按钮都不可见。我将不胜感激任何建议。似乎没有其他人尝试过这样做,这有点令人惊讶。Stackoverflow 想要对问题进行更长的描述,但我真的没有什么要说的了。
import os, sys, time
from PyQt5.QtWidgets import QApplication, QDialog, QGridLayout, QPushButton, QTextEdit, \
QToolButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
class Popup(QDialog):
"""
Overview
--------
This class implements a substitute for the QMessageBox widget. `Popup` allows the user to
define an arbitrary number of buttons with arbitrary names. The widget can be either modal
or non-modal.
Note
----
`Popup` inherits from `QDialog` rather than `QWidget`; otherwise, it would not function as a
popup widget.
"""
# Section 11.1: Constructor.
def __init__(self, *, text="Your message goes here.", button_names=None, icon='warning',
width=900, height=300, button_style_sheets=None, button_widths=None, parent=None,
title='', modal=True):
"""
Inputs
------
`text` is a string containing the text to be displayed. One can use HTML to control
fonts, colors, etc. If one does not specify the font, one gets the default font, which is
very small.
`title` is the window title, which is by default an empty string.
`button_names`, which is `None`, a single string, or a list of strings, optionally names
the buttons to be displayed below the text. If there are multiple buttons, these are
displayed from left to right in the order specified.
If `button_names` is `None`, the `icon` string determines which buttons are displayed:
'critical' causes a single 'OK' button to be displayed; anything else causes a pair of
buttons, with labels 'Yes' and 'No', to be displayed.
`icon` is the name of the icon to be displayed. The default is 'warning', which causes
the code to load the file `warning.ico`.
`width` and `height` are the width and height of the window in units of pixels.
"""
super().__init__(parent=parent)
self.setModal(modal)
self.setWindowTitle(title)
self.grid= QGridLayout()
self.setLayout(self.grid)
self.textedit= QTextEdit(text)
self.textedit.setFixedWidth (width)
self.textedit.setFixedHeight(height)
self.textedit.setStyleSheet('font-size: 14pt;')
if button_names is None:
# Assign default button names:
if icon.startswith('warning') or icon.startswith('stop'):
button_names= ['OK']
else:
button_names= ['Yes', 'No']
elif isinstance(button_names, str):
button_names= [button_names]
if button_style_sheets is None:
button_style_sheets= []
for button_name in button_names:
if button_name.lower() in ('y', 'yes'):
button_style_sheets.append('font-size: 14pt; font-weight: bold; color: #00AA00')
elif button_name.lower() in ('n', 'no'):
button_style_sheets.append('font-size: 14pt; font-weight: bold; color: #FF0000')
else:
button_style_sheets.append('font-size: 14pt; font-weight: bold')
if isinstance(button_widths, int):
# All button widths are the same:
button_widths= len(button_names) * [button_widths]
elif button_widths is None:
button_widths= []
for button_name in button_names:
# Set button widths based on the number of characters in the name.
# The resulting widths are not perfect.
button_widths.append(20 * (len(button_name) + 2))
if icon:
# There is an icon. ==> The icon occupies the first position in both rows and
# everything else is pushed one position to the right.
if icon.endswith('.png'):
from PIL.ImageQt import ImageQt
qim= ImageQt(icon)
pix= QPixmap.fromImage(qim)
label= QLabel()
label.setPixmap(pix)
self.grid.addWidget(label , 0, 0, 1, 1)
else:
self.icon= QToolButton()
self.icon.setIcon(QIcon(icon))
self.grid.addWidget(self.icon , 0, 0, 1, 1)
self.grid.addWidget(self.textedit, 0, 1, 1, len(button_names)+1)
else:
self.grid.addWidget(self.textedit, 0, 0, 1, len(button_names)+1)
self.buttons= []
for i, button_name in enumerate(button_names):
button= QPushButton(button_name, parent=self)
button.setFixedWidth(button_widths[i])
if isinstance(button_style_sheets, str):
button.setStyleSheet(button_style_sheets)
else:
button.setStyleSheet(button_style_sheets[i])
self.buttons.append(button)
self.grid.addWidget(button, 1, i+bool(icon), 1, 1, alignment=Qt.AlignRight)
def make_func(button_name):
def set_result():
self.result= button_name
return set_result
def close():
self.close()
button.clicked.connect(make_func(button_name))
button.clicked.connect(close)
# end for i, button_name in button_names
# end def __init__
app = QApplication(sys.argv)
popup= Popup(text="Now is the time for all good men to come to the aid of their country.",
button_names=['Yes', 'No', 'Maybe'])
popup.show()
time.sleep(3)
解决方案
您不应该在 Qt 中使用 time.sleep(),如果您希望程序显示一段时间,请使用调用 quit() 方法的 QTimer。
QTimer.singleShot(3 * 1000, QCoreApplication.quit)
sys.exit(app.exec_())
如果您只想关闭弹出窗口而不是所有其他窗口,请将其连接到 close() 方法:
QTimer.singleShot(3 * 1000, popup.close)
sys.exit(app.exec_())
推荐阅读
- python - Windows长度矩阵转向量,提取数据
- javascript - 如何在 Symfony 项目中使用 jQuery 和 webpack-encore?
- javascript - React.js - 无法访问对象数组中的值
- jquery - 通过 AJAX 调用传递数据导致失败
- java - 使用 Java 从 YAML 文件中删除 Key:Value 属性
- python - 如何使用 python 应用 IDW 插值来使用 Plotly 绘制 3D 曲面
- angularjs - 带有已编译模板的 angularjs 验证指令不反映 dom 上的“最大”属性更改
- java - 可以使用spring kafka API的客户端和使用apache kafka API的服务器端实现spring请求回复吗?
- reactjs - 使用反应钩子创建一个计时器
- php - 碳日期比较和日期格式