[英]PyQt5 QFileDialog stops application from closing
I am trying to write a PyQt5 application that does the following: 我正在尝试编写一个执行以下操作的PyQt5应用程序:
My problem is that I haven't found a way to get the QfileDialog to automatically open (2) that doesn't cause the application to hang when the main window is closed. 我的问题是我还没有找到一种使QfileDialog自动打开的方法(2),该方法不会在关闭主窗口时导致应用程序挂起。 Basic example of code can be found below:
基本的代码示例可以在下面找到:
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QWidget,
QHBoxLayout, QCalendarWidget, QScrollArea, QFileDialog, QAction, QFrame)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QAction(QIcon('/usr/share/icons/breeze/places/64/folder-open.svg'), 'Open', self)
self.openAction.triggered.connect(self.openDialog)
self.menubar = QMenuBar(self)
fileMenu = self.menubar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.event_widgets = EventWidgets(self)
self.setMenuBar(self.menubar)
self.setCentralWidget(self.event_widgets)
def openDialog(self):
ics_path = QFileDialog.getOpenFileName(self, 'Open file', '/home/michael/')
class EventWidgets(QWidget):
def __init__(self, parent):
super(EventWidgets, self).__init__(parent)
self.initUI()
def initUI(self):
self.calendar = QCalendarWidget(self)
self.frame = QFrame()
self.scrollArea = QScrollArea()
self.scrollArea.setWidget(self.frame)
horizontal_box = QHBoxLayout()
horizontal_box.addWidget(self.calendar)
horizontal_box.addWidget(self.scrollArea)
self.setLayout(horizontal_box)
if __name__ == '__main__':
app = QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
app_window.openDialog()
sys.exit(app.exec_())
Code has been tested on KDE Neon and Arch Linux, both have same issue. 代码已经在KDE Neon和Arch Linux上进行了测试,它们都有相同的问题。
I can get round this issue by handling the close event of the Main Window manually - ie adding this function to MainWindow: 我可以通过手动处理Main Window的close事件来解决此问题-即将此函数添加到MainWindow:
def closeEvent(self, event):
sys.exit()
But I am not sure a) why this is necessary b) if it is best practice. 但是我不确定a)为什么这样做是必要的b)如果是最佳实践。
I tried your code on macOS Sierra and it works as it's supposed to. 我在macOS Sierra上尝试了您的代码,它按预期运行。 However I would propose a different approach to solve your problem.
但是,我会提出另一种方法来解决您的问题。
What you could do is to implement the showEvent()
function in your MainWindow
class, which is executed whenever a widget is displayed (either using .show()
or .showMaximized()
) and trigger your custom slot to open the QFileDialog
. 您可以做的是在
MainWindow
类中实现showEvent()
函数,该函数在显示小部件时执行(使用.show()
或.showMaximized()
)并触发您的自定义插槽以打开QFileDialog
。 When doing this you could make use of a single shot timer to trigger the slot with some minimal delay: the reason behind this is that if you simply open the dialog from within the showEvent()
, you will see the dialog window but not the MainWindow
below it (because the QFileDialog
is blocking the UI until the user perform some action). 这样做时,您可以利用单个计时器来以最小的延迟触发插槽:其背后的原因是,如果
showEvent()
内部打开对话框,则会看到对话框窗口,但看不到MainWindow
在它下面(因为QFileDialog
阻止了UI,直到用户执行某些操作为止)。 The single shot timer adds some delay to the opening of the QFileDialog
, and allows the MainWindow
to be rendered behind the modal dialog. 单次计时器增加了
QFileDialog
的打开延迟,并允许MainWindow
在模式对话框的后面呈现。 Here is a possible solution (not that I made some minor changes to your code, which you should be able to easily pick up): 这是一个可能的解决方案(不是我对您的代码做了一些小的更改,您应该可以轻松地进行修改):
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QtWidgets.QAction('Open', self)
self.openAction.triggered.connect(self.openDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.event_widgets = EventWidgets(self)
self.setCentralWidget(self.event_widgets)
def showEvent(self, showEvent):
QtCore.QTimer.singleShot(50, self.openDialog)
@QtCore.pyqtSlot()
def openDialog(self):
ics_path = QtWidgets.QFileDialog.getOpenFileName(self, 'Open file', '/Users/daniele/')
class EventWidgets(QtWidgets.QWidget):
def __init__(self, parent):
super(EventWidgets, self).__init__(parent)
self.calendar = QtWidgets.QCalendarWidget(self)
self.frame = QtWidgets.QFrame()
self.scrollArea = QtWidgets.QScrollArea()
self.scrollArea.setWidget(self.frame)
horizontal_box = QtWidgets.QHBoxLayout()
horizontal_box.addWidget(self.calendar)
horizontal_box.addWidget(self.scrollArea)
self.setLayout(horizontal_box)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.