当 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 ...然后个人 QMenu
s... 不起作用。
我不清楚如何处理这个“活动状态”业务,或者为什么连接到 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()
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 ...然后个人 QMenu
s... 不起作用。
我不清楚如何处理这个“活动状态”业务,或者为什么连接到 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()