Python 3.x 为什么PyQt5显示我的第一个文件对话框而不是第二个?
我正在尝试使用PyQt5为python项目创建一个基本的前端gui。具体来说,我想从两件事开始。首先,我想提示用户选择一个输入数据文件。然后,我想提示用户选择一个可以保存文件的目录 下面是代码的工作示例我的问题是,当代码中有两个提示给用户时(先是输入文件,然后是保存目录),为什么用户只收到一个提示。代码没有抛出错误;注释掉输入文件例程(Python 3.x 为什么PyQt5显示我的第一个文件对话框而不是第二个?,python-3.x,user-interface,dialog,pyqt5,widget,Python 3.x,User Interface,Dialog,Pyqt5,Widget,我正在尝试使用PyQt5为python项目创建一个基本的前端gui。具体来说,我想从两件事开始。首先,我想提示用户选择一个输入数据文件。然后,我想提示用户选择一个可以保存文件的目录 下面是代码的工作示例我的问题是,当代码中有两个提示给用户时(先是输入文件,然后是保存目录),为什么用户只收到一个提示。代码没有抛出错误;注释掉输入文件例程(self.select\u save\u directory()(在接口的初始化方法中)将允许运行保存目录例程 首先,所有的进口 import sys from
self.select\u save\u directory()
(在接口的初始化方法中)
将允许运行保存目录例程
首先,所有的进口
import sys
from PyQt5 import QtWidgets # QtGui, QtCore
然后,提示用户选择输入.csv文件的小部件
class FileSelectionWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Click here and select the data file you want to read")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
self._fpath = None
@property
def fpath(self):
return self._fpath
def on_clicked(self):
dialog = QtWidgets.QFileDialog(
self,
"Select input file",
"path",
"*.csv",
supportedSchemes=["file"],
options=QtWidgets.QFileDialog.DontUseNativeDialog)
fpath = dialog.getOpenFileName(None, 'Open file', '/home')[0]
self._fpath = fpath
self.close()
print(self.fpath) # verify
然后,提示用户选择保存目录的小部件
class DirectorySelectionWidget(QtWidgets.QWidget):
"""
This class allows the user to select the directory
to save files into via gui.
"""
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Click here and select the directory \nin which you would like to save files")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
self._savedir = None
@property
def savedir(self):
return self._savedir
def on_clicked(self):
dialog = QtWidgets.QFileDialog()
savedir = dialog.getExistingDirectory(None, "Select directory")
self._savedir = savedir
self.close()
print(self.savedir) # verify
我计划添加现有的后端
class BackEnd():
def __init__(self):
super().__init__()
# data processing functions
最后,接口从后端继承方法,并可以调用/实例化上面的UI方法
class Interface(BackEnd):
def __init__(self):
"""
"""
super().__init__()
self.select_data_file()
self.select_save_directory()
... # more back-end things
def select_data_file(self):
app = QtWidgets.QApplication(sys.argv)
file_selection_widget = FileSelectionWidget()
file_selection_widget.show()
sys.exit(app.exec_())
def select_save_directory(self):
app = QtWidgets.QApplication(sys.argv)
directory_selection_widget = DirectorySelectionWidget()
directory_selection_widget.show()
sys.exit(app.exec_())
if __name__ == '__main__':
interface = Interface()
:
退出Python
这与PyQt无关。问题是select_data_file
和select_save_directory
都以sys.exit
结束,导致程序立即退出,无论以后调用什么函数
此外,如果要重用对话框(或在程序生命周期内显示其他内容),通常最好避免重新创建QApplication
您可以在main
中启动一个QApplication,然后将类更改为QDialog而不是QWidget,并使用exec()
而不是show()
显示它们。这允许保持您现在(使用app.exec()
)的相同“阻塞”效果,该效果将在对话框关闭后立即清除,然后您可以在需要时显示其他窗口
请注意,为了防止程序进一步退出,您应该在实际退出时使用并手动调用QApplication.quit()
最后,请注意getOpenFileName
和getExistingDirectory
都是QFileDialog的静态方法。它们返回一个新的预构建文件对话框实例,因此在此之前创建一个实例是没有意义的。
您需要将参数添加到静态函数本身
def on_clicked(self):
fpath, _ = QtWidgets.QFileDialog.getOpenFileName(
None, 'Select input file', '/home', '*.csv',
options=QtWidgets.QFileDialog.DontUseNativeDialog)
if fpath:
self._fpath = fpath
self.close()
:
退出Python
这与PyQt无关。问题是select_data_file
和select_save_directory
都以sys.exit
结束,导致程序立即退出,无论以后调用什么函数
此外,如果要重用对话框(或在程序生命周期内显示其他内容),通常最好避免重新创建QApplication
您可以在main
中启动一个QApplication,然后将类更改为QDialog而不是QWidget,并使用exec()
而不是show()
显示它们。这允许保持您现在(使用app.exec()
)的相同“阻塞”效果,该效果将在对话框关闭后立即清除,然后您可以在需要时显示其他窗口
请注意,为了防止程序进一步退出,您应该在实际退出时使用并手动调用QApplication.quit()
最后,请注意getOpenFileName
和getExistingDirectory
都是QFileDialog的静态方法。它们返回一个新的预构建文件对话框实例,因此在此之前创建一个实例是没有意义的。
您需要将参数添加到静态函数本身
def on_clicked(self):
fpath, _ = QtWidgets.QFileDialog.getOpenFileName(
None, 'Select input file', '/home', '*.csv',
options=QtWidgets.QFileDialog.DontUseNativeDialog)
if fpath:
self._fpath = fpath
self.close()
我没有足够的代表投票,但是谢谢。关于sys.exit
和只使用一个QApplication
的部分很有意义。关于你的最后一段,当你说“在那之前创建一个实例是毫无意义的”时,你指的是什么实例?在点击的的第一行中,你正在创建一个新实例(dialog=qtwidget.QFileDialog(…)
)。该实例永远不会被使用,因为使用getOpenFileName
会创建一个全新的实例。见我的编辑,其中包括完整的功能,并摆脱了这一部分,因为它是不必要的,我没有足够的代表投票,但谢谢。关于sys.exit
和只使用一个QApplication
的部分很有意义。关于你的最后一段,当你说“在那之前创建一个实例是毫无意义的”时,你指的是什么实例?在点击的的第一行中,你正在创建一个新实例(dialog=qtwidget.QFileDialog(…)
)。该实例永远不会被使用,因为使用getOpenFileName
会创建一个全新的实例。请参阅我的编辑,它包含了完整的功能,并删除了该部分,因为它是不必要的