繁体   English   中英

PyQt5 QFileDialog停止关闭应用程序

[英]PyQt5 QFileDialog stops application from closing

我正在尝试编写一个执行以下操作的PyQt5应用程序:

  • 创建并打开一个主窗口。 MainWindow具有打开QFileDialog窗口的功能。
  • 显示主窗口后,可以通过两种方式(1)从名为“打开”的文件菜单选项自动触发打开QFileDialog的功能(2)。

我的问题是我还没有找到一种使QfileDialog自动打开的方法(2),该方法不会在关闭主窗口时导致应用程序挂起。 基本的代码示例可以在下面找到:

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_())

代码已经在KDE Neon和Arch Linux上进行了测试,它们都有相同的问题。

我可以通过手动处理Main Window的close事件来解决此问题-即将此函数添加到MainWindow:

def closeEvent(self, event):
        sys.exit()

但是我不确定a)为什么这样做是必要的b)如果是最佳实践。

我在macOS Sierra上尝试了您的代码,它按预期运行。 但是,我会提出另一种方法来解决您的问题。

您可以做的是在MainWindow类中实现showEvent()函数,该函数在显示小部件时执行(使用.show().showMaximized() )并触发您的自定义插槽以打开QFileDialog 这样做时,您可以利用单个计时器来以最小的延迟触发插槽:其背后的原因是,如果showEvent()内部打开对话框,则会看到对话框窗口,但看不到MainWindow在它下面(因为QFileDialog阻止了UI,直到用户执行某些操作为止)。 单次计时器增加了QFileDialog的打开延迟,并允许MainWindow在模式对话框的后面呈现。 这是一个可能的解决方案(不是我对您的代码做了一些小的更改,您应该可以轻松地进行修改):

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM