PyQt5 非常简单的按钮输入对话框
PyQt5 very simple button input dialog
我想我会尝试 pyqt(5) 进行更改,并希望在脚本启动时创建一个简单的对话框,让用户从三个选项中选择一个。
我的目标是像这样的弹出窗口(在脚本启动时),它将在按下其中一个按钮时关闭,并且 returns 按下按钮的值:
这就是我尝试实现它的方式:
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QDialogButtonBox
input_db_connection="None"
class MyDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Choose Database connection")
self.buttonBox=QDialogButtonBox(self)
for option in ["Production Read", "Production Read&Write", "Development"]:
b = QPushButton(option)
b.clicked.connect(lambda x: return_and_close(option))
self.buttonBox.addButton(b,0)
del b
def return_and_close(value):
global input_db_connection
print(value)
input_db_connection=value
self.close()
app = QApplication([])
dg = MyDialog()
dg.show()
app.exec()
print(input_db_connection)
我使用了一个全局变量,因为我没有找到从 QApplication return 任何东西的方法。
无论我按哪个按钮,输出的都是“Development”,输入的最后一个选项?
主要问题在 lambda scope 中:lambda:
中的内容只有在执行时才会被评估。
单击按钮时,for
循环已经完成,此时 option
将是循环中分配的最后一个值。
解决方案是“强制”关键字参数,以便在内部范围内有一个持久引用。请注意,Qt 按钮的 clicked
信号有一个 checked
参数,您 必须 在 lambda 位置参数中考虑它。
那么,与其创建全局变量(这几乎总是一个糟糕的选择),不如正确使用 QDialog 的功能:
from PyQt5.QtWidgets import *
class MyDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Choose Database connection")
layout = QVBoxLayout(self)
self.buttonBox = QDialogButtonBox(self)
layout.addWidget(self.buttonBox)
states = [
(0, "Production Read"),
(1, "Production Read&Write"),
(2, "Development"),
]
for value, option in states:
b = QPushButton(option)
b.clicked.connect(lambda _, value=value: self.done(value))
self.buttonBox.addButton(b, 0)
app = QApplication([])
dg = MyDialog()
print(dg.exec())
补充说明:
- 总是使用layout managers,创建子widgets是不够的,尝试手动设置几何体还是不行,除非你对Qt事件有很深的了解和深刻的体验、尺寸提示和政策;
- 不要不必要地调用
del
(在这种情况下它也完全没有意义,因为它只会删除 python 引用,并且它是一个局部变量,会在每个 for 循环和__init__
returns 时收集的垃圾,没用);
- 尽可能避免使用局部函数,而总是更喜欢实例方法;
我想我会尝试 pyqt(5) 进行更改,并希望在脚本启动时创建一个简单的对话框,让用户从三个选项中选择一个。
我的目标是像这样的弹出窗口(在脚本启动时),它将在按下其中一个按钮时关闭,并且 returns 按下按钮的值:
这就是我尝试实现它的方式:
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QDialogButtonBox
input_db_connection="None"
class MyDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Choose Database connection")
self.buttonBox=QDialogButtonBox(self)
for option in ["Production Read", "Production Read&Write", "Development"]:
b = QPushButton(option)
b.clicked.connect(lambda x: return_and_close(option))
self.buttonBox.addButton(b,0)
del b
def return_and_close(value):
global input_db_connection
print(value)
input_db_connection=value
self.close()
app = QApplication([])
dg = MyDialog()
dg.show()
app.exec()
print(input_db_connection)
我使用了一个全局变量,因为我没有找到从 QApplication return 任何东西的方法。
无论我按哪个按钮,输出的都是“Development”,输入的最后一个选项?
主要问题在 lambda scope 中:lambda:
中的内容只有在执行时才会被评估。
单击按钮时,for
循环已经完成,此时 option
将是循环中分配的最后一个值。
解决方案是“强制”关键字参数,以便在内部范围内有一个持久引用。请注意,Qt 按钮的 clicked
信号有一个 checked
参数,您 必须 在 lambda 位置参数中考虑它。
那么,与其创建全局变量(这几乎总是一个糟糕的选择),不如正确使用 QDialog 的功能:
from PyQt5.QtWidgets import *
class MyDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Choose Database connection")
layout = QVBoxLayout(self)
self.buttonBox = QDialogButtonBox(self)
layout.addWidget(self.buttonBox)
states = [
(0, "Production Read"),
(1, "Production Read&Write"),
(2, "Development"),
]
for value, option in states:
b = QPushButton(option)
b.clicked.connect(lambda _, value=value: self.done(value))
self.buttonBox.addButton(b, 0)
app = QApplication([])
dg = MyDialog()
print(dg.exec())
补充说明:
- 总是使用layout managers,创建子widgets是不够的,尝试手动设置几何体还是不行,除非你对Qt事件有很深的了解和深刻的体验、尺寸提示和政策;
- 不要不必要地调用
del
(在这种情况下它也完全没有意义,因为它只会删除 python 引用,并且它是一个局部变量,会在每个 for 循环和__init__
returns 时收集的垃圾,没用); - 尽可能避免使用局部函数,而总是更喜欢实例方法;