当 QFileDialog 关闭时,菜单栏有时不会变灰

Menubar sometimes does not become un-greyed when QFileDialog closes

OS:W10。这可能很重要。如果您在不同的平台上有不同的结果,反馈会很有帮助。

这是一个MRE。如果你 运行 它并按 Ctrl+O,菜单标签会变成灰色。如果您通过单击“打开”按钮或使用其助记符 (Alt+O) select QFileDialog 中的文件,打开文件对话框将关闭,“文件”和“帮助”菜单变灰。

但是,如果您再次按 Ctrl+O,这次在“文件名”框中输入文件名 (QLineEdit),然后按 Return,对话框被关闭(成功 selection 结果)但“文件”和“帮助”菜单保持灰色。它看起来像这样:

import sys, os 
from PyQt5 import QtWidgets, QtCore, QtGui

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Greying of menus MRE')
        self.setGeometry(QtCore.QRect(100, 100, 400, 200))

        menubar = QtWidgets.QMenuBar(self)
        self.setMenuBar(menubar)
        self.files_menu = QtWidgets.QMenu('&Files', self)
        menubar.addMenu(self.files_menu)
        self.help_menu = QtWidgets.QMenu('&Help', self)
        menubar.addMenu(self.help_menu)
        self.new_action = QtWidgets.QAction('&New', self)
        self.files_menu.addAction(self.new_action)
        self.open_action = QtWidgets.QAction('&Open', self)
        self.files_menu.addAction(self.open_action)
        self.open_action.setShortcut("Ctrl+O")
        self.open_action.triggered.connect(self.open_file)
                
    def focusInEvent(self, event ):
        print('main_window focusInEvent')
        super().focusInEvent(event)

    def focusOutEvent(self, event ):
        print('main_window focusOutEvent')
        super().focusInEvent(event)
        
    def activateWindow(self):
        print('main_window activateWindow')
        super().activateWindow()    
        
    def open_file(self):
        print('open file')
        
        main_window_self = self

        # open_doc_dialog = QtWidgets.QFileDialog(self.get_main_window())
        class OpenDocFileDialog(QtWidgets.QFileDialog):
            def accepted(self):
                print('accepted')
                super().accepted()

            def accept(self):
                print('accept')
                super().accept()
        
            def close(self):
                print('close')
                super().close()
        
            def done(self, r):
                print(f'done r {r}')
                
                # neither of these solves the problem:
                # main_window_self.activateWindow()
                # main_window_self.files_menu.activateWindow()
                super().done(r)
        
            def hide(self):
                print(f'hide')
                super().hide()
                
            def focusInEvent(self, event ):
                print('focusInEvent')
                super().focusInEvent(event)
        
            def focusOutEvent(self, event ):
                print('focusOutEvent')
                super().focusInEvent(event)
                
            def activateWindow(self):
                print('activateWindow')
                super().activateWindow()    
                
        
        open_doc_dialog = OpenDocFileDialog(self)
        open_doc_dialog.setWindowTitle('Choose file')
        open_doc_dialog.setDirectory(os.getcwd())
        # we cannot use the native dialog, because we need control over the UI
        options = open_doc_dialog.Options(open_doc_dialog.DontUseNativeDialog)
        open_doc_dialog.setOptions(options)
        open_doc_button = open_doc_dialog.findChild(QtWidgets.QDialogButtonBox).button(QtWidgets.QDialogButtonBox.Open)
        lineEdit = open_doc_dialog.findChild(QtWidgets.QLineEdit)
        
        # this does not solve the problem
        # lineEdit.returnPressed.disconnect()
        # lineEdit.returnPressed.connect(open_doc_button.click)
        
        print(f'open_doc_button {open_doc_button}, lineEdit {lineEdit}')
        # show the dialog
        dialog_code = open_doc_dialog.exec()
        if dialog_code != QtWidgets.QDialog.Accepted: return
        sel_files = open_doc_dialog.selectedFiles()
        print(f'sel_files: {sel_files}')

                
app = QtWidgets.QApplication([])
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())    

这个问题可以理解,如果没有解决,参考

请注意,此变灰不是禁用。正如上面 link 中所解释的,这与菜单(或其标签)的“active/inactive 状态”有关。菜单始终保持启用状态,但在这种情况下,打开文件对话框显示时不可能知道,因为它是模态的。在对话框消失后单击一个菜单,或者只是将鼠标悬停在它上面,足以将它们都取消灰色...

根据我的理解,解释是“文件名”框 QLineEdit 有一个信号 returnPressed,它似乎激活了一些与当您使用“选择”按钮。你可以看到我已经尝试重新连接该信号,但无济于事。

似乎调用了 QFileDialog 的方法 done 但是对话框关闭了(不像 close!),所以我尝试“激活”主要 window ...然后个人 QMenus... 不起作用。

我不清楚如何处理这个“活动状态”业务,或者为什么连接到 returnPressed 的插槽(似乎)无法在其他广告位设法做到了。

编辑
搜索 Musicamante 的“未经修饰”的建议让我找到了这个:

lineEdit.returnPressed.disconnect()
def return_pressed():
    style = main_window_self.menubar.style()
    style.unpolish(main_window_self.menubar)
    open_doc_button.click()
lineEdit.returnPressed.connect(return_pressed)

...不幸的是,这不起作用。

终于搞定了,感谢Musicamante的建议:

lineEdit.returnPressed.disconnect()
def return_pressed():
    style = main_window_self.menubar.style()
    style.unpolish(main_window_self.menubar)
    open_doc_button.click()
    main_window_self.menubar.repaint()
lineEdit.returnPressed.connect(return_pressed)

...我实际上尝试了几次,只是为了确保它按预期进行。所以实际上,幸运的是,在这种情况下不需要单次定时器。

这看起来像是一个可能与 Windows 相关的错误,因为我无法在 Linux 上重现它。作为解决方法,您可以尝试在对话框关闭后强制重绘:

# show the dialog
dialog_code = open_doc_dialog.exec()
self.menubar.repaint()